import unittest
from unittest import mock

import requests
from aws_lambda_tools.common.user_type import ConioUser
from bithustler_client.client.client import BithustlerClient
from bithustler_client.generated_protobuf import bithustler_pb2
from cards_client.client.client import CardsClient
from cards_client.generated_protobuf import base_pb2
from requests import Response
from vault_client.client.auth_client import VaultAuthClient
from vault_client.client.client_definition import VaultClient
from vault_client.generated_protobuf import vault_pb2

from conio_sdk.common import exceptions
from conio_sdk.services.conio.user.vault_service import VaultService
from etc.settings import VaultAuthCredentials


class TestUserServiceRefreshSession(unittest.TestCase):
    def _change_user_info(self, user_info: dict):
        self.user_info = user_info
        self.pb2_user = vault_pb2.User(**self.user_info)
        self.user = ConioUser(data=self.user_info)

    def setUp(self):
        self.external_reference = 'an_external_reference'
        self._change_user_info({
            'reference_key_id': 'a reference key id',
            'external_references': [self.external_reference],
            'status': vault_pb2.LOCKED
        })
        self.vault_auth_credentials = \
            VaultAuthCredentials(
                'http://test.vault.com',
                'vault_auth_username',
                'vault_auth_password'
            )
        self.cards_client = mock.create_autospec(CardsClient)
        self.payer = base_pb2.MsgCreatePayerResponse()
        self.payer.data.payer_id = 'a payer id'
        self.cards_client.create_payer.return_value = self.payer
        self.bithustler_client = mock.create_autospec(BithustlerClient)
        self.seller = bithustler_pb2.Seller(id='a seller id')
        self.bithustler_client.create_seller.return_value = self.seller
        self.vault_client = mock.create_autospec(VaultClient)
        self.vault_auth_client = mock.create_autospec(VaultAuthClient)
        self.sut = VaultService(
            self.vault_client,
            self.vault_auth_client,
            self.vault_auth_credentials,
            self.cards_client,
            self.bithustler_client
        )

    @mock._patch_object(requests, 'post')
    def test_logout(self, post_mock):
        def _post(url: str, *_, **__):
            self.assertEqual('http://test.vault.com/logout', url)
            resp = Response()
            resp.status_code = 200
            resp.headers = {'Content-Type': 'application/json'}
            return resp
        post_mock.side_effect = _post
        self.sut.logout('a token')

    @mock._patch_object(requests, 'post')
    def test_logout_invalid_token(self, post_mock):
        for err in (401, 403):
            def _post(url: str, *_, **__):
                self.assertEqual('http://test.vault.com/logout', url)
                resp = Response()
                resp.status_code = err
                return resp
            post_mock.side_effect = _post
            with self.assertRaises(exceptions.NotAuthenticatedException):
                self.sut.logout('a token')
