"""Tests for Activedocs Toolbox feature"""

import re

import pytest

from testsuite.toolbox import constants
from testsuite.toolbox import toolbox
from testsuite.utils import blame, blame_desc, randomize
from testsuite import rawobj

SWAGGER_LINK = 'https://raw.githubusercontent.com/OAI/OpenAPI-Specification/master/examples/v2.0/json/petstore.json'


@pytest.fixture(scope="module")
def my_app_plan(request, custom_app_plan, service):
    """App. plans fixture"""
    return custom_app_plan(rawobj.ApplicationPlan(blame(request, "silver")), service)


@pytest.fixture(scope="module")
def my_activedoc(request, service, oas3_body, custom_active_doc):
    """This fixture creates active document for service."""
    rawad = rawobj.ActiveDoc(
                name=blame(request, 'activedoc'),
                service=service, body=oas3_body,
                description=blame_desc(request))
    return custom_active_doc(rawad)


@pytest.fixture(scope="module")
def empty_list(service, my_app_plan, my_activedoc, create_cmd):
    """Fixture for empty list constant"""
    # these fixtures should be created for being able to list empty list
    # pylint: disable=unused-argument
    return toolbox.run_cmd(create_cmd('list'))['stdout']


@pytest.fixture(scope="module")
def create_cmd(threescale_src1):
    """ Returns function of activedocs command creation """

    def _create_cmd(cmd, args=None):
        args = args or ''
        return f"activedocs {cmd} {threescale_src1} {args}"

    return _create_cmd


def parse_create_command_out(output):
    """Returns id from 'create' command output."""
    return re.match(r"ActiveDocs '([^']+)' has been created with ID: (\d+)", output).groups()


# Global variable for metrics' values to check
out_variables = {}


def test_list1(empty_list, service, my_app_plan, my_activedoc, create_cmd):
    """Run command 'list'"""
    # pylint: disable=unused-argument
    ret = toolbox.run_cmd(create_cmd('list'))
    assert not ret['stderr']
    assert ret['stdout'] == empty_list
    to_cmp = r'ID\tNAME\tSYSTEM_NAME\tSERVICE_ID\tPUBLISHED\tSKIP_SWAGGER_VALIDATIONS\tCREATED_AT\tUPDATED_AT'
    assert re.findall(to_cmp, ret['stdout'])
    to_cmp = fr"{my_activedoc['id']}\t{my_activedoc['name']}\t{my_activedoc['system_name']}\t"
    to_cmp += fr"{service['id']}\t{str(my_activedoc['published']).lower()}\t"
    to_cmp += fr"{str(my_activedoc['skip_swagger_validations']).lower()}\t"
    assert re.findall(to_cmp, ret['stdout'])


def test_create1(threescale, create_cmd):
    """Run command 'create' to create first activedoc"""
    out_variables['ac1_name'] = randomize('activedoc1', 3)
    ret = toolbox.run_cmd(create_cmd('create', f"{out_variables['ac1_name']} {SWAGGER_LINK}"))
    assert not ret['stderr']

    out_variables['ac1'] = parse_create_command_out(ret['stdout'])
    out_variables['ac1_entity'] = threescale.active_docs[int(out_variables['ac1'][1])].entity


def test_create2(service, threescale, create_cmd):
    """Run command 'create' to create second activedoc"""
    out_variables['ac2_name'] = randomize('activedoc2', 3)
    cmd = f"{out_variables['ac2_name']} {SWAGGER_LINK} --service-id {service['id']} "
    cmd += '--skip-swagger-validations=true --description="activedoc2 desc" --published '
    cmd += f"--system-name={randomize('activedoc_system', 3)}"
    ret = toolbox.run_cmd(create_cmd('create', cmd))
    assert not ret['stderr']

    out_variables['ac2'] = parse_create_command_out(ret['stdout'])
    out_variables['ac2_entity'] = threescale.active_docs[int(out_variables['ac2'][1])].entity


def test_list2(empty_list, service, my_activedoc, threescale, create_cmd):
    """Run command 'list' active docs"""
    # pylint: disable=unused-argument
    ret = toolbox.run_cmd(create_cmd('list'))
    assert not ret['stderr']
    for line in empty_list.splitlines():
        assert line in ret['stdout']

    to_cmp = fr"{out_variables['ac1_entity']['id']}\t{out_variables['ac1_entity']['name']}\t"
    to_cmp += fr"{out_variables['ac1_entity']['system_name']}\t\(empty\)\tfalse\tfalse"
    assert re.findall(to_cmp, ret['stdout'])
    to_cmp = fr"{out_variables['ac2_entity']['id']}\t{out_variables['ac2_entity']['name']}\t"
    to_cmp += fr"{out_variables['ac2_entity']['system_name']}\t{service['id']}\ttrue\ttrue"
    assert re.findall(to_cmp, ret['stdout'])


def test_apply1(service, threescale, create_cmd):
    """Run command 'apply' to update first activedoc"""
    cmd = fr"{out_variables['ac1_entity']['system_name']} --description='updated' "
    cmd += fr"--publish --service-id={service['id']} --name={out_variables['ac1_entity']['name'] + '_updated'} "
    cmd += r'--skip-swagger-validations=true '
    ret = toolbox.run_cmd(create_cmd('apply', cmd))
    assert not ret['stderr']
    assert re.findall(fr"Applied ActiveDocs id: {out_variables['ac1'][1]}", ret['stdout'])
    out_variables['ac3'] = re.match(r'Applied ActiveDocs id: (\d+)', ret['stdout']).groups()[0]
    out_variables['ac3_entity'] = threescale.active_docs[int(out_variables['ac3'])].entity


def test_delete1(create_cmd):
    """Run command 'delete' to delete first active doc"""
    ret = toolbox.run_cmd(create_cmd('delete', f"{out_variables['ac1'][1]}"))
    assert not ret['stderr']
    assert f"ActiveDocs with id: {out_variables['ac1'][1]} deleted" in ret['stdout']


def test_delete2(create_cmd):
    """Run command 'delete' to delete second active doc"""
    ret = toolbox.run_cmd(create_cmd('delete', f"{out_variables['ac2'][1]}"))
    assert not ret['stderr']
    assert f"ActiveDocs with id: {out_variables['ac2'][1]} deleted" in ret['stdout']


def test_list3(empty_list, create_cmd):
    """Run command 'list' active doc"""
    ret = toolbox.run_cmd(create_cmd('list'))
    assert not ret['stderr']
    assert empty_list in ret['stdout']


def test_check_active_docs_values():
    """Check values of created and updated active docs."""
    # This comment shows clearly what attributes are checked
    # 'name', 'published', 'skip_swagger_validations', 'system_name'

    attr_list = constants.ACTIVEDOCS_CMP_ATTRS
    attr_list.add('body')
    # remove description because of https://issues.redhat.com/browse/THREESCALE-5836
    attr_list.add('description')
    toolbox.check_object(out_variables['ac1_entity'], attr_list, [
        out_variables['ac1_name'], False, False, out_variables['ac1_entity']['system_name']])
    toolbox.check_object(out_variables['ac2_entity'], attr_list, [
        out_variables['ac2_name'], True, True, out_variables['ac2_entity']['system_name']])
    toolbox.check_object(out_variables['ac3_entity'], attr_list, [
        out_variables['ac1_name'] + '_updated', True, True, out_variables['ac1_entity']['system_name']])

"""Tests for Activedocs Toolbox feature"""

import re

import pytest

from testsuite.toolbox import constants
from testsuite.toolbox import toolbox
from testsuite.utils import blame, blame_desc, randomize
from testsuite import rawobj

SWAGGER_LINK = 'https://raw.githubusercontent.com/OAI/OpenAPI-Specification/master/examples/v2.0/json/petstore.json'


@pytest.fixture(scope="module")
def my_app_plan(request, custom_app_plan, service):
    """App. plans fixture"""
    return custom_app_plan(rawobj.ApplicationPlan(blame(request, "silver")), service)


@pytest.fixture(scope="module")
def my_activedoc(request, service, oas3_body, custom_active_doc):
    """This fixture creates active document for service."""
    rawad = rawobj.ActiveDoc(
                name=blame(request, 'activedoc'),
                service=service, body=oas3_body,
                description=blame_desc(request))
    return custom_active_doc(rawad)


@pytest.fixture(scope="module")
def empty_list(service, my_app_plan, my_activedoc, create_cmd):
    """Fixture for empty list constant"""
    # these fixtures should be created for being able to list empty list
    # pylint: disable=unused-argument
    return toolbox.run_cmd(create_cmd('list'))['stdout']


@pytest.fixture(scope="module")
def create_cmd(threescale_src1):
    """ Returns function of activedocs command creation """

    def _create_cmd(cmd, args=None):
        args = args or ''
        return f"activedocs {cmd} {threescale_src1} {args}"

    return _create_cmd


def parse_create_command_out(output):
    """Returns id from 'create' command output."""
    return re.match(r"ActiveDocs '([^']+)' has been created with ID: (\d+)", output).groups()


# Global variable for metrics' values to check
out_variables = {}


def test_list1(empty_list, service, my_app_plan, my_activedoc, create_cmd):
    """Run command 'list'"""
    # pylint: disable=unused-argument
    ret = toolbox.run_cmd(create_cmd('list'))
    assert not ret['stderr']
    assert ret['stdout'] == empty_list
    to_cmp = r'ID\tNAME\tSYSTEM_NAME\tSERVICE_ID\tPUBLISHED\tSKIP_SWAGGER_VALIDATIONS\tCREATED_AT\tUPDATED_AT'
    assert re.findall(to_cmp, ret['stdout'])
    to_cmp = fr"{my_activedoc['id']}\t{my_activedoc['name']}\t{my_activedoc['system_name']}\t"
    to_cmp += fr"{service['id']}\t{str(my_activedoc['published']).lower()}\t"
    to_cmp += fr"{str(my_activedoc['skip_swagger_validations']).lower()}\t"
    assert re.findall(to_cmp, ret['stdout'])


def test_create1(threescale, create_cmd):
    """Run command 'create' to create first activedoc"""
    out_variables['ac1_name'] = randomize('activedoc1', 3)
    ret = toolbox.run_cmd(create_cmd('create', f"{out_variables['ac1_name']} {SWAGGER_LINK}"))
    assert not ret['stderr']

    out_variables['ac1'] = parse_create_command_out(ret['stdout'])
    out_variables['ac1_entity'] = threescale.active_docs[int(out_variables['ac1'][1])].entity


def test_create2(service, threescale, create_cmd):
    """Run command 'create' to create second activedoc"""
    out_variables['ac2_name'] = randomize('activedoc2', 3)
    cmd = f"{out_variables['ac2_name']} {SWAGGER_LINK} --service-id {service['id']} "
    cmd += '--skip-swagger-validations=true --description="activedoc2 desc" --published '
    cmd += f"--system-name={randomize('activedoc_system', 3)}"
    ret = toolbox.run_cmd(create_cmd('create', cmd))
    assert not ret['stderr']

    out_variables['ac2'] = parse_create_command_out(ret['stdout'])
    out_variables['ac2_entity'] = threescale.active_docs[int(out_variables['ac2'][1])].entity


def test_list2(empty_list, service, my_activedoc, threescale, create_cmd):
    """Run command 'list' active docs"""
    # pylint: disable=unused-argument
    ret = toolbox.run_cmd(create_cmd('list'))
    assert not ret['stderr']
    for line in empty_list.splitlines():
        assert line in ret['stdout']

    to_cmp = fr"{out_variables['ac1_entity']['id']}\t{out_variables['ac1_entity']['name']}\t"
    to_cmp += fr"{out_variables['ac1_entity']['system_name']}\t\(empty\)\tfalse\tfalse"
    assert re.findall(to_cmp, ret['stdout'])
    to_cmp = fr"{out_variables['ac2_entity']['id']}\t{out_variables['ac2_entity']['name']}\t"
    to_cmp += fr"{out_variables['ac2_entity']['system_name']}\t{service['id']}\ttrue\ttrue"
    assert re.findall(to_cmp, ret['stdout'])


def test_apply1(service, threescale, create_cmd):
    """Run command 'apply' to update first activedoc"""
    cmd = fr"{out_variables['ac1_entity']['system_name']} --description='updated' "
    cmd += fr"--publish --service-id={service['id']} --name={out_variables['ac1_entity']['name'] + '_updated'} "
    cmd += r'--skip-swagger-validations=true '
    ret = toolbox.run_cmd(create_cmd('apply', cmd))
    assert not ret['stderr']
    assert re.findall(fr"Applied ActiveDocs id: {out_variables['ac1'][1]}", ret['stdout'])
    out_variables['ac3'] = re.match(r'Applied ActiveDocs id: (\d+)', ret['stdout']).groups()[0]
    out_variables['ac3_entity'] = threescale.active_docs[int(out_variables['ac3'])].entity


def test_delete1(create_cmd):
    """Run command 'delete' to delete first active doc"""
    ret = toolbox.run_cmd(create_cmd('delete', f"{out_variables['ac1'][1]}"))
    assert not ret['stderr']
    assert f"ActiveDocs with id: {out_variables['ac1'][1]} deleted" in ret['stdout']


def test_delete2(create_cmd):
    """Run command 'delete' to delete second active doc"""
    ret = toolbox.run_cmd(create_cmd('delete', f"{out_variables['ac2'][1]}"))
    assert not ret['stderr']
    assert f"ActiveDocs with id: {out_variables['ac2'][1]} deleted" in ret['stdout']


def test_list3(empty_list, create_cmd):
    """Run command 'list' active doc"""
    ret = toolbox.run_cmd(create_cmd('list'))
    assert not ret['stderr']
    assert empty_list in ret['stdout']


def test_check_active_docs_values():
    """Check values of created and updated active docs."""
    # This comment shows clearly what attributes are checked
    # 'name', 'published', 'skip_swagger_validations', 'system_name'

    attr_list = constants.ACTIVEDOCS_CMP_ATTRS
    attr_list.add('body')
    # remove description because of https://issues.redhat.com/browse/THREESCALE-5836
    attr_list.add('description')
    toolbox.check_object(out_variables['ac1_entity'], attr_list, [
        out_variables['ac1_name'], False, False, out_variables['ac1_entity']['system_name']])
    toolbox.check_object(out_variables['ac2_entity'], attr_list, [
        out_variables['ac2_name'], True, True, out_variables['ac2_entity']['system_name']])
    toolbox.check_object(out_variables['ac3_entity'], attr_list, [
        out_variables['ac1_name'] + '_updated', True, True, out_variables['ac1_entity']['system_name']])

Tests for Activedocs Toolbox feature App. plans fixture This fixture creates active document for service. Fixture for empty list constant # these fixtures should be created for being able to list empty list # pylint: disable=unused-argument Returns function of activedocs command creation Returns id from 'create' command output. # Global variable for metrics' values to check Run command 'list' # pylint: disable=unused-argument Run command 'create' to create first activedoc Run command 'create' to create second activedoc Run command 'list' active docs # pylint: disable=unused-argument Run command 'apply' to update first activedoc Run command 'delete' to delete first active doc Run command 'delete' to delete second active doc Run command 'list' active doc Check values of created and updated active docs. # This comment shows clearly what attributes are checked # 'name', 'published', 'skip_swagger_validations', 'system_name' # remove description because of https://issues.redhat.com/browse/THREESCALE-5836