import mock
import requests

from orm.services.customer_manager.cms_rest.controllers.v1.orm.group\
    import roles
from orm.services.customer_manager.cms_rest.logic.error_base import ErrorStatus
from orm.services.customer_manager.cms_rest.model import GroupModels
from orm.tests.unit.cms import FunctionalTest
from wsme.exc import ClientSideError

group_logic_mock = None


class TestGroupsRoleController(FunctionalTest):
    def setUp(self):
        FunctionalTest.setUp(self)

        roles.authentication = mock.MagicMock()

        roles.GroupLogic = get_mock_group_logic
        roles.GroupLogic.return_error = 0

        roles.utils = mock.MagicMock()
        roles.utils.make_transid.return_value = 'some_trans_id'
        roles.utils.audit_trail.return_value = None
        roles.utils.make_uuid.return_value = 'some_uuid'

        roles.err_utils = mock.MagicMock()

    def tearDown(self):
        FunctionalTest.tearDown(self)

    def test_assign_roles_to_group(self):
        # given
        requests.post = mock.MagicMock(return_value=ResponseMock(200))

        # when
        response = self.app.post_json('/v1/orm/groups/{groups id}/roles/',
                                      GROUPS_ROLE_JSON)

        # assert
        assert response.status_int == 200
        assert roles.utils.audit_trail.called
        assert group_logic_mock.assign_roles_called

    def test_assign_roles_to_group_fail(self):
        # given
        requests.post = mock.MagicMock()

        roles.GroupLogic.return_error = 1

        roles.err_utils.get_error = mock.MagicMock(
            return_value=ClientSideError("blabla", 500))
        # when
        response = self.app.post_json('/v1/orm/groups/{groups id}/roles/',
                                      GROUPS_ROLE_JSON, expect_errors=True)
        # assert
        self.assertEqual(response.status_int, 500)

    def test_assign_roles_to_group_bad_request(self):
        # given
        requests.post = mock.MagicMock()

        roles.GroupLogic.return_error = 2
        roles.err_utils.get_error = mock.MagicMock(
            return_value=ClientSideError("blabla", 404))

        # when
        response = self.app.post_json('/v1/orm/groups/{groups_id}/roles/',
                                      GROUPS_ROLE_JSON, expect_errors=True)

        # assert
        self.assertEqual(response.status_int, 404)

    @mock.patch.object(roles, 'request')
    def test_unassign_roles_to_group(self, request):
        # given
        requests.delete = mock.MagicMock(return_value=ResponseMock(204))
        request.headers = {'X-RANGER-Requester': "rds_resource_service_proxy"}

        response = self.app.delete(
            '/v1/orm/groups/{groups id}/roles/{role name}/{type}/{type id}')

        # assert
        assert response.status_int == 204
        assert roles.utils.audit_trail.called
        assert group_logic_mock.unassign_roles_called

    def test_unassign_roles_to_group_fail(self):
        # given
        requests.delete = mock.MagicMock()

        roles.GroupLogic.return_error = 1
        roles.err_utils.get_error = mock.MagicMock(
            return_value=ClientSideError("blabla", 500))

        # when
        response = self.app.delete(
            '/v1/orm/groups/{groups id}/roles/{role name}/{type}/{type id}',
            expect_errors=True)

        # assert
        self.assertEqual(response.status_int, 500)

    @mock.patch.object(roles, 'request')
    def test_unassign_roles_to_group_bad_request(self, request):
        # given
        requests.delete = mock.MagicMock()
        request.headers = {'X-RANGER-Requester': "rds_resource_service_proxy"}

        roles.GroupLogic.return_error = 2
        roles.err_utils.get_error = mock.MagicMock(
            return_value=ClientSideError("blabla", 404))

        # when
        response = self.app.delete(
            '/v1/orm/groups/{groups id}/roles/{role name}/{type}/{type id}',
            expect_errors=True)

        # assert
        self.assertEqual(response.status_int, 404)


def get_mock_group_logic():
    global group_logic_mock
    group_logic_mock = mock.MagicMock()

    if roles.GroupLogic.return_error == 0:
        res = GroupModels.RoleResultWrapper(transaction_id='1',
                                            roles=[],
                                            links={},
                                            created='1')

        res1 = GroupModels.RoleResultWrapper(transaction_id='1',
                                             roles=[],
                                             links={},
                                             created='1')

        group_logic_mock.assign_roles.return_value = res
        group_logic_mock.unassign_roles.return_value = res1

    elif roles.GroupLogic.return_error == 1:
        group_logic_mock.assign_roles.side_effect = SystemError()
        group_logic_mock.unassign_roles.side_effect = SystemError()

    else:
        group_logic_mock.assign_roles.side_effect = ErrorStatus(
            status_code=404)
        group_logic_mock.unassign_roles.side_effect = ErrorStatus(
            status_code=404)

    return group_logic_mock


class ResponseMock:
    def __init__(self, status_code=200):
        self.status_code = status_code


GROUPS_ROLE_JSON = [
    {
        "project": "project-id",
        "roles": [
            "role1",
            "role2"
        ]
    }
]
