# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0

from datetime import datetime
from dateutil.tz import tzlocal
import json
import os
from unittest import TestCase
from unittest.mock import patch, MagicMock

with patch("boto3.client") as boto_client_mock:
    from functions.identity.CognitoFbCallbackHandler import index


# Patch Lambda environment variables:
@patch.dict(os.environ, {
    'APP_CLIENT_ID': '1234567890abcdefghijklmnop',
    'BOOTSTRAP_BUCKET': 'do-not-delete-gamekit-dev-123456789012-foogamename',
    'GAMEKIT_KMS_KEY_ARN': 'arn:aws:kms:us-west-2:123456789012:key/12345678-abcd-1234-abcd-123456789012',
    'GAMEKIT_KMS_KEY_ID': '12345678-abcd-1234-abcd-123456789012',
    'IDENTITY_TABLE_NAME': 'gamekit_dev_foogamename_identities',
    'REDIRECT_URI': 'https://123abcdefg.execute-api.us-west-2.amazonaws.com/dev/identity/fbtokenresp',
    'USER_POOL_DOMAIN': 'https://gamekit-dev-foogamename.auth.us-west-2.amazoncognito.com',
    'USER_POOL_ID': 'us-west-2_123456789',
})
class TestIndex(TestCase):
    def setUp(self):
        index.s3_client = MagicMock()
        index.cidp_client = MagicMock()
        index.dynamodb_client = MagicMock()

    @patch('functions.identity.CognitoFbCallbackHandler.index._get_user_info')
    @patch('functions.identity.CognitoFbCallbackHandler.index._check_object_exists_in_s3')
    @patch('functions.identity.CognitoFbCallbackHandler.index.crypto.decrypt_blob')
    @patch('functions.identity.CognitoFbCallbackHandler.index._exchange_code_for_access_token')
    @patch('functions.identity.CognitoFbCallbackHandler.index.ddb.boto3')
    def test_can_link_facebook_account_to_existing_user_successfully(self,
                                                                     mock_gamekithelpers_ddb_boto3,
                                                                     mock_exchange_code_for_access_token,
                                                                     mock_decrypt_blob,
                                                                     check_object_exists_in_s3,
                                                                     mock_get_user_info):
        # Arrange
        event = self.get_lambda_event()
        context = None
        mock_exchange_code_for_access_token.return_value = (self.get_exchange_code_for_access_token())
        mock_decrypt_blob.return_value = (True, self.get_decrypted_state_for_existing_user())
        check_object_exists_in_s3.return_value = False
        mock_ddb_table = mock_gamekithelpers_ddb_boto3.resource('dynamodb').Table()
        mock_ddb_table.get_item.return_value = {
            'Item': {
                "created_at": "2021-07-06T20:22:25.799025+00:00",
                "gk_user_hash_key": "1Hk6RU80eQvVpg9yyWaNIdrbmSvejd1hVfeVFl0woeQ=",
                "gk_user_id": "0d386660-8f62-4da7-b31c-43ab1237c540",
                "gk_user_id_hash": "nnk9/21CoT8BEmWT7o/XZPtb7FJPdXFC5hUilV7W0fA=",
                "updated_at": "2021-07-06T20:22:25.799025+00:00"
            }
        }
        mock_get_user_info.return_value = {
            'sub': 'abcdefgh-1234-1234-1234-abcdefghijkl',
            'username': 'Facebook_123456789012345'
        }
        index.cidp_client.admin_get_user.return_value = self.get_cognito_user_info()

        # Act
        result = index.lambda_handler(event, context)

        # Assert
        self.assertEqual(200, result['statusCode'])
        mock_ddb_table.update_item.assert_called_once()

    @patch('functions.identity.CognitoFbCallbackHandler.index._write_object_to_s3')
    @patch('functions.identity.CognitoFbCallbackHandler.index._get_user_info')
    @patch('functions.identity.CognitoFbCallbackHandler.index._check_object_exists_in_s3')
    @patch('functions.identity.CognitoFbCallbackHandler.index._exchange_code_for_access_token')
    @patch('functions.identity.CognitoFbCallbackHandler.index.crypto.decrypt_blob')
    @patch('functions.identity.CognitoFbCallbackHandler.index.ddb.boto3')
    @patch('functions.identity.CognitoFbCallbackHandler.index.crypto.boto3')
    def test_can_create_account_for_new_user_successfully(self,
                                                          mock_gamekithelpers_crypto_boto3,
                                                          mock_gamekithelpers_ddb_boto3,
                                                          mock_decrypt_blob,
                                                          mock_exchange_code_for_access_token,
                                                          check_object_exists_in_s3,
                                                          mock_get_user_info,
                                                          write_object_to_s3):
        # Arrange
        event = self.get_lambda_event()
        context = None
        mock_exchange_code_for_access_token.return_value = (self.get_exchange_code_for_access_token())
        check_object_exists_in_s3.return_value = False
        mock_get_user_info.return_value = {
            'sub': 'abcdefgh-1234-1234-1234-abcdefghijkl',
            'username': 'Facebook_123456789012345'
        }
        index.cidp_client.admin_get_user.return_value = self.get_cognito_user_info()
        mock_ddb_table = mock_gamekithelpers_ddb_boto3.resource('dynamodb').Table()
        mock_ddb_table.query.return_value = self.get_dynamodb_query_response()
        mock_gamekithelpers_crypto_boto3.client('kms').generate_data_key.return_value = {
            'CiphertextBlob': b'\x01\x02\x03\x00x\xdd\xc7vu\x9d\xf2\x80]\x98\xa0\\\x86\xfb\xd7QM\x94$,j\xa6a~\x1f\xb9\xd5\xb3\x1b\xc8\xf6\xe7\xf7\x01\x02\xbb\xac\x131\xd2\xf4\x8aw\xd0E\xcd\xda\xca`N\x00\x00\x00~0|\x06\t*\x86H\x86\xf7\r\x01\x07\x06\xa0o0m\x02\x01\x000h\x06\t*\x86H\x86\xf7\r\x01\x07\x010\x1e\x06\t`\x86H\x01e\x03\x04\x01.0\x11\x04\x0c@\x14\xdb\xf3\x93n\xab\x9b;\x0f\xe4s\x02\x01\x10\x80;7\x1e\x7fNr\x9f>bI*\x05C\xe9;\xeb\xf6\xce\x17Sn\xd2\x90x\x98\xa7\x8c\x0b\x0b\xa4U+t\xe6\xe8T\x16\xaf~)?fN\xa4\xc7\t\x02\x892\xfa\xfc\x18\xccCDUk\xd9\xd24',
            'Plaintext': b'\x9ff$\xca\xe6;=;\x02\xe1[\xce\xc1\xda\xa0&\x81M\x83\xb4oK~q>\xf4\xde\xc2\x91m\xca\x12',
        }
        mock_decrypt_blob.return_value = (True, self.get_decrypted_state_for_new_user())

        # Act
        result = index.lambda_handler(event, context)

        # Assert
        self.assertEqual(200, result['statusCode'])
        mock_ddb_table.put_item.assert_called_once()
        self.assertEqual(2, write_object_to_s3.call_count)

    def test_lambda_returns_a_400_error_code_when_the_querystring_state_is_missing(self):
        # Arrange
        event = self.get_lambda_event()
        context = None

        # Simulate the case when 'state' is completely missing from the queryStringParameters:
        event['queryStringParameters'].pop('state')

        # Act
        result = index.lambda_handler(event, context)

        # Assert
        self.assertEqual(400, result['statusCode'])
        self.assert_did_not_write_to_dynamodb(index.dynamodb_client)

    def test_lambda_returns_a_400_error_code_when_the_querystring_state_is_empty(self):
        sub_tests = [
            ("None", None),
            ("empty string", ''),
            ("one whitespace character", ' '),
            ("many whitespace characters", '   '),
        ]

        for test_name, state in sub_tests:
            with self.subTest(test_name):
                # Arrange
                event = self.get_lambda_event()
                context = None

                event['queryStringParameters']['state'] = state

                # Act
                result = index.lambda_handler(event, context)

                # Assert
                self.assertEqual(400, result['statusCode'])
                self.assert_did_not_write_to_dynamodb(index.dynamodb_client)

    @patch('functions.identity.CognitoFbCallbackHandler.index.crypto.decrypt_blob')
    @patch('functions.identity.CognitoFbCallbackHandler.index._exchange_code_for_access_token')
    def test_lambda_returns_an_error_code_when_the_decrypted_state_is_malformed(self,
                                                                                mock_exchange_code_for_access_token,
                                                                                mock_decrypt_blob):
        sub_tests = [
            ("missing request_id", 400, b'{"expiration": 9999999999, "source_ip": "12.123.123.12"}'),
            ("missing expiration", 400, b'{"request_id": "7b8961cb-19db-47e3-88cb-afcd9884b81d", '
                                        b'"source_ip": "12.123.123.12"}'),
            ("missing source_ip", 400, b'{"request_id": "7b8961cb-19db-47e3-88cb-afcd9884b81d",'
                                       b'"expiration": 9999999999}'),
            ("source_ip mismatch", 400, b'{"request_id": "7b8961cb-19db-47e3-88cb-afcd9884b81d",'
                                        b'"expiration": 9999999999, "source_ip": "12.123.123.123"}'),
            ("request has expired", 403, b'{"request_id": "7b8961cb-19db-47e3-88cb-afcd9884b81d", '
                                         b'"source_ip": "12.123.123.12", "expiration": 100}'),
        ]

        for test_name, error_code, decrypted_state in sub_tests:
            with self.subTest(test_name):
                # Arrange
                event = self.get_lambda_event()
                context = None
                mock_exchange_code_for_access_token.return_value = (self.get_exchange_code_for_access_token())
                mock_decrypt_blob.return_value = (True, decrypted_state)

                # Act
                result = index.lambda_handler(event, context)

                # Assert
                self.assertEqual(error_code, result['statusCode'])
                self.assert_did_not_write_to_dynamodb(index.dynamodb_client)

    @patch('functions.identity.CognitoFbCallbackHandler.index._check_object_exists_in_s3')
    @patch('functions.identity.CognitoFbCallbackHandler.index.crypto.decrypt_blob')
    @patch('functions.identity.CognitoFbCallbackHandler.index._exchange_code_for_access_token')
    def test_lambda_returns_a_200_success_code_when_the_completion_callback_file_already_exists(self,
                                                                                                mock_exchange_code_for_access_token,
                                                                                                mock_decrypt_blob,
                                                                                                check_object_exists_in_s3):
        # Arrange
        event = self.get_lambda_event()
        context = None
        mock_exchange_code_for_access_token.return_value = (self.get_exchange_code_for_access_token())
        mock_decrypt_blob.return_value = (True, self.get_decrypted_state_for_new_user())
        check_object_exists_in_s3.return_value = True

        # Act
        result = index.lambda_handler(event, context)

        # Assert
        self.assertEqual(200, result['statusCode'])
        self.assert_did_not_write_to_dynamodb(index.dynamodb_client)

    @staticmethod
    def assert_did_not_write_to_dynamodb(mock_dynamodb: MagicMock):
        mock_dynamodb.put_item.assert_not_called()
        mock_dynamodb.update_item.assert_not_called()

    @staticmethod
    def get_lambda_event():
        return {
            'resource': '/identity/fbtokenresp',
            'path': '/identity/fbtokenresp',
            'httpMethod': 'GET',
            'headers': {
                'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
                'Accept-Encoding': 'gzip,deflate,br',
                'Accept-Language': 'en-US,en;q=0.5',
                'CloudFront-Forwarded-Proto': 'https',
                'CloudFront-Is-Desktop-Viewer': 'true',
                'CloudFront-Is-Mobile-Viewer': 'false',
                'CloudFront-Is-SmartTV-Viewer': 'false',
                'CloudFront-Is-Tablet-Viewer': 'false',
                'CloudFront-Viewer-Country': 'US',
                'Host': '123abcdefg.execute-api.us-west-2.amazonaws.com',
                'Referer': 'https://www.facebook.com/v11.0/dialog/oauth/read/',
                'upgrade-insecure-requests': '1',
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Firefox/78.0',
                'Via': '2.0 4f3feb5c4393987d42d1971d404d7cea.cloudfront.net (CloudFront)',
                'X-Amz-Cf-Id': 'hczAVi_Amqcn7Ag9TMxZvEQrrnsLBqBayXWnGvRU3_9cHncFCbyduw==',
                'X-Amzn-Trace-Id': 'Root=1-60e7790d-329f1f724ba7741850373cfa',
                'X-Forwarded-For': '12.123.123.12, 56.567.567.567',
                'X-Forwarded-Port': '443',
                'X-Forwarded-Proto': 'https'
            },
            'multiValueHeaders': {
                'Accept': ['text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'],
                'Accept-Encoding': ['gzip,deflate,br'],
                'Accept-Language': ['en-US,en;q=0.5'],
                'CloudFront-Forwarded-Proto': ['https'],
                'CloudFront-Is-Desktop-Viewer': ['true'],
                'CloudFront-Is-Mobile-Viewer': ['false'],
                'CloudFront-Is-SmartTV-Viewer': ['false'],
                'CloudFront-Is-Tablet-Viewer': ['false'],
                'CloudFront-Viewer-Country': ['US'],
                'Host': ['123abcdefg.execute-api.us-west-2.amazonaws.com'],
                'Referer': ['https://www.facebook.com/v11.0/dialog/oauth/read/'],
                'upgrade-insecure-requests': ['1'],
                'User-Agent': ['Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Firefox/78.0'],
                'Via': ['2.0 4f3feb5c4393987d42d1971d404d7cea.cloudfront.net (CloudFront)'],
                'X-Amz-Cf-Id': ['hczAVi_Amqcn7Ag9TMxZvEQrrnsLBqBayXWnGvRU3_9cHncFCbyduw=='],
                'X-Amzn-Trace-Id': ['Root=1-60e7790d-329f1f724ba7741850373cfa'],
                'X-Forwarded-For': ['12.123.123.12, 56.567.567.567'],
                'X-Forwarded-Port': ['443'],
                'X-Forwarded-Proto': ['https']
            },
            'queryStringParameters': {
                'code': '470d5e7e-2f29-4e12-a83d-221605d5a7df',
                'state': 'AAAAuAECAwB43cd2dZ3ygF2YoFyG 9dRTZQkLGqmYX4fudWzG8j25/cB62gLCvpghdqhcaSxP TQtAAAAH4wfAYJKoZIhvcNAQcGoG8wbQIBADBoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDMH29Xiv6ZiQIhNXGQIBEIA72fPQlMq7xB/M66hp0GGQqysQtKbpUdCPT0Hf1EcRRGRfYcWF2IbQnI57u1JYYjIOhv6A0a/yOCwK/kRnQUFBQUFCZzUzajY0REgydzBwbmhRSEhweGRNckx2NTdjVFVRaVNUNmhjNFRJOFJLcVlLaE40X1JCQVhPTi1NNVVGZWZyNS1aZ0dWb3cyVkpYMEJBRDNyeXJDZ3NYbTZRN0haZWdhM19LTGZpeWJDNHY2UHQyVFViNmdDUzhOdDBMNWk3cGhhcGVTSXpJcEQ2NV81VVZJek5icHdTWVhLUTFRekJfaEtBWUljbGg5S3ViWnZLMV9DN1VKb3NGdllPcVlVT1l2dDZYekw='
            },
            'multiValueQueryStringParameters': {
                'code': ['470d5e7e-2f29-4e12-a83d-221605d5a7df'],
                'state': ['AAAAuAECAwB43cd2dZ3ygF2YoFyG 9dRTZQkLGqmYX4fudWzG8j25/cB62gLCvpghdqhcaSxP TQtAAAAH4wfAYJKoZIhvcNAQcGoG8wbQIBADBoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDMH29Xiv6ZiQIhNXGQIBEIA72fPQlMq7xB/M66hp0GGQqysQtKbpUdCPT0Hf1EcRRGRfYcWF2IbQnI57u1JYYjIOhv6A0a/yOCwK/kRnQUFBQUFCZzUzajY0REgydzBwbmhRSEhweGRNckx2NTdjVFVRaVNUNmhjNFRJOFJLcVlLaE40X1JCQVhPTi1NNVVGZWZyNS1aZ0dWb3cyVkpYMEJBRDNyeXJDZ3NYbTZRN0haZWdhM19LTGZpeWJDNHY2UHQyVFViNmdDUzhOdDBMNWk3cGhhcGVTSXpJcEQ2NV81VVZJek5icHdTWVhLUTFRekJfaEtBWUljbGg5S3ViWnZLMV9DN1VKb3NGdllPcVlVT1l2dDZYekw=']
            },
            'pathParameters': None,
            'stageVariables': None,
            'requestContext': {
                'resourceId': 'xxrv33',
                'resourcePath': '/identity/fbtokenresp',
                'httpMethod': 'GET',
                'extendedRequestId': 'CK_aHFVZPHcFaAQ=',
                'requestTime': '08/Jul/2021:22:15:41 +0000',
                'path': '/dev/identity/fbtokenresp',
                'accountId': '123456789012',
                'protocol': 'HTTP/1.1',
                'stage': 'dev',
                'domainPrefix': '123abcdefg',
                'requestTimeEpoch': 1625782541323,
                'requestId': 'a82d27e1-f89c-4304-9c43-dfe5c2c4464f',
                'identity': {
                    'cognitoIdentityPoolId': None,
                    'accountId': None,
                    'cognitoIdentityId': None,
                    'caller': None,
                    'sourceIp': '12.123.123.12',
                    'principalOrgId': None,
                    'accessKey': None,
                    'cognitoAuthenticationType': None,
                    'cognitoAuthenticationProvider': None,
                    'userArn': None,
                    'userAgent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Firefox/78.0',
                    'user': None
                },
                'domainName': '123abcdefg.execute-api.us-west-2.amazonaws.com',
                'apiId': '123abcdefg'
            },
            'body': None,
            'isBase64Encoded': False
        }

    @staticmethod
    def get_exchange_code_for_access_token():
        token_resp_dict = {
            'id_token': 'eyJraWQiOiJxbmg3NlwvUjRHRnRkSmVZbTh3elFRc2cwXC9jUnZaemZtRDhLS2NRYXZvXC9FPSIsImFsZyI6IlJTMjU2In0.eyJhdF9oYXNoIjoicS0wbk81Zjdub1dkb1lBRVhCdUx6QSIsInN1YiI6ImEyNDJiNDNmLTdkYmEtNGY3OS05ZDgyLWZhMDg4MWQwNDRiNCIsImNvZ25pdG86Z3JvdXBzIjpbInVzLXdlc3QtMl9FMmxlWWR6ZUhfRmFjZWJvb2siXSwiaXNzIjoiaHR0cHM6XC9cL2NvZ25pdG8taWRwLnVzLXdlc3QtMi5hbWF6b25hd3MuY29tXC91cy13ZXN0LTJfRTJsZVlkemVIIiwiY29nbml0bzp1c2VybmFtZSI6IkZhY2Vib29rXzExNjkxNDQxMzk3ODAzNiIsIm9yaWdpbl9qdGkiOiIwY2FmMDI5Yi04M2Q1LTQxNTctYWNiYS1mYjMyNDNlOWUwNTAiLCJhdWQiOiI1N283NmhndWRjbmg4cWFhbTAyOG9uY29qNyIsImlkZW50aXRpZXMiOlt7InVzZXJJZCI6IjExNjkxNDQxMzk3ODAzNiIsInByb3ZpZGVyTmFtZSI6IkZhY2Vib29rIiwicHJvdmlkZXJUeXBlIjoiRmFjZWJvb2siLCJpc3N1ZXIiOm51bGwsInByaW1hcnkiOiJ0cnVlIiwiZGF0ZUNyZWF0ZWQiOiIxNjI1NzgyNTQwNjM0In1dLCJ0b2tlbl91c2UiOiJpZCIsImF1dGhfdGltZSI6MTYyNTkwMDI1MiwiZXhwIjoxNjI1OTAzODUyLCJpYXQiOjE2MjU5MDAyNTIsImp0aSI6IjQyZGZlMzNjLTIwYWUtNDQyZi05YTg0LWMxNWY5NzQ4Mzk1ZCJ9.G3s1nK76Yz9ancOi7BuRd-ZeJVcxuXqYPnbNDEvVukDlL0Yxj23kXeWYIxndnXyexs0IVgi3ml8OjW0POVBaMRFsVtXCkox-nAZXqcObeXYLm0gbbkiXjGl73nVWPl-lBZpB8dCTMpcPDFGwpP22hHbhHH85lYnelppzFQANikktFJ9SdQ0N_aknVIT8YrTkkiElOW0dWJqmqluIle5jb2lgdCfuJl50UyIBT7lt1lPLL6MPFvDA0u4aw6JfhNU7a5E7Ib4pFCW-LoN_Od_gPAfj6GRcY-RbWfGuHM88_apIblfVKcalEivO8O_U-ORFYJHw2pi3OchEKhKY2dFj_w',
            'access_token': 'eyJraWQiOiJvK3NVaXBRSXBQRnp0bFFWcGhweWV2bjQzdXd2cEhwZmNtWHRxSUZlT3BFPSIsImFsZyI6IlJTMjU2In0.eyJzdWIiOiJhMjQyYjQzZi03ZGJhLTRmNzktOWQ4Mi1mYTA4ODFkMDQ0YjQiLCJjb2duaXRvOmdyb3VwcyI6WyJ1cy13ZXN0LTJfRTJsZVlkemVIX0ZhY2Vib29rIl0sImlzcyI6Imh0dHBzOlwvXC9jb2duaXRvLWlkcC51cy13ZXN0LTIuYW1hem9uYXdzLmNvbVwvdXMtd2VzdC0yX0UybGVZZHplSCIsInZlcnNpb24iOjIsImNsaWVudF9pZCI6IjU3bzc2aGd1ZGNuaDhxYWFtMDI4b25jb2o3Iiwib3JpZ2luX2p0aSI6IjBjYWYwMjliLTgzZDUtNDE1Ny1hY2JhLWZiMzI0M2U5ZTA1MCIsInRva2VuX3VzZSI6ImFjY2VzcyIsInNjb3BlIjoiY29tLmF3cy5nZGtcL2dkay5pZGVudGl0eSBvcGVuaWQiLCJhdXRoX3RpbWUiOjE2MjU5MDAyNTIsImV4cCI6MTYyNTkwMzg1MiwiaWF0IjoxNjI1OTAwMjUyLCJqdGkiOiI5NGNkNjUzOS01NThjLTQ3NDQtYWI2OS1mZmNkMGE5MjlkMjEiLCJ1c2VybmFtZSI6IkZhY2Vib29rXzExNjkxNDQxMzk3ODAzNiJ9.bJHOk-gDO7jTklHZPslnwkPnyAClsbjzhEY4vDPZiYpMJYi5IdZp5HQkdeuSNK9DNzN_lx9TSdwVQdzarZhjqrWh7iojQUdc016Csb7X2nFSExNASUx4GmcuKTIZdJhXni5P1Wj_LEpNIsLc_j_FbYkzB3Kp6BtoNJRmjQ8V_lNcKTsjo0btgiuvwVuBWerQIrjoqQsD2vj9-JD929Fhuhl6BxGdNlywZC5oXndnt9oipxioEudqpDOapsWaKLrFb1yKvQsh4CCdWXG4S_9tIOUr-Pi74XMIQRDxR5d-TAJR8flTneZ5AHI1IIpX26zIPOCGwlZLi5BlvxkK25ylGw',
            'refresh_token': 'eyJjdHkiOiJKV1QiLCJlbmMiOiJBMjU2R0NNIiwiYWxnIjoiUlNBLU9BRVAifQ.I7gJohTTKwoHy4yWI-eYxcCXKzmNzt-ktKsqyxQBCOV_VJOP5MjFyfLtbvKo6c3IgrCzBsc9gAw9xnCBCLC5YVf4-dmXgu1QzX3PXIEanynIF2YeeEQ7ZxIkySk9ijgBC7TvXmTF4ayg5c1_rWwAi86DdEjvkqce5M174liWLnB7wrCYWNj7jTItyN2cPFFa4zn4757Uaz_zMhjtSKMRLJz6QAm0v0lD3RmPH1TM0i-KtoENONv6BlYX2zhuAB8ca5HBkL4opkyPTEfBKOgRuqSkCz2qpHgyjann5bueJVFt87Y932E98GvnxEQr6WcuLQDTEM_xQV_fmVKZ72unPw.JPLY9K1TEsUM58nW.iKNPzBiy6XLdLLCBcAtRVhnZsBKtL6PYNXbxOLiBl53N-L1-QAxAbEvASoFLd8Vodw7-ZaRL17YJUGLpeacHh93iMZN8sT-fheiuUf0vvlhaeJnSAJPIgjKzCmRiZiln1bHNJNQLlSP4t1S6S5IJUWtEZsDdAW-g5jaRGJtwej0e1mQcjcAt4fu5y4BWRqDzXx3bKZjql8aE1_tcrrRomk1qK4s5XCEGZSecvyBOuuqioVx0R5UvN3U3DTwcIfBH_SwGIfG71nvKPOL0FByffVvX4z3GtBl27yUDnDKDMxUd0sJLyCxBNq2aEVw6vNnxJPhbioI1-WsqdR5cqVFgwLSd0Xnc3UUGH3i7Td051VU8YmBIwpuyk0eVE8yn-eipXzpyjjIvwTbXc35xElUX-bOjSvXlKJPlN35Gxl2IL-Uz7yRn5YYwNO1mFqpRnujYyH86GPF6ZD2MxwD1-4AU6kpHmoxgfDRn3Rsyo6kNLiDgQEPjQIHFSMWIfOJPngibj7CEz9QRKTmps1f52c19vEJmwYWIEKLysuPsIAIrAO1Z2JDEpMtBBEqJKhofK7gl4I4E7LyF2dMSawQw3exbntoPdxXmi3a942aQU99b2CWeVoJLrJMs2eIo_974CZYqL2DMB1kQjkT_m3oBMyjAiO9kNeGh5jKY9GtDZevS1u8R6PRVhkUM8EVjHMaU0gjI3RVBhMFPgPmhzeP7QLjt2KA4IxPnRz9LFL2EX74po2xSGsKDHoZ_vLX-qVQxX6EXozQeF0bxkFT1sYtMMZM48ls5Dhc-f8AtxlU68nWg_OxAuvToq2_Q0XDjMX4fxmM2oG6hu-by60CKVOBShoe0quc0cp5OfbrbRDSpEZWvxk3RPzJ1cDOrsYVQ3I9WJmALFzYLXTS0-SIxz9QAe3CjVANOncGy0zV9BO_3EZvJ_ZevbUUibQKMrsiZUIm0gMIbCfhG-O0BBKovgZuGVJNaMW5_24THjaTKomA662sAI6OnCQ-gi0nJrYV5H3oeT05TbRDkE1AvgpkWWnOv84aJqANHqF1j26iOiTwWey3c7Debs8AC95QOnAbbx9f8iY6GHFUJUYDqAnzQD18BkHfQuTsEf1iyqvGCWhfv1LQZ9nGIA4PbJtE0aQa_Uc_qFI4T4HHzTbkM8iNgUldtwMrOE7ZkPq_dwP1EpCq5DDJkhNjx19xImOVdTR1sTnwbMB8gJh49QhkycJDJhtW_rBRJOd72fNpt1c8EGDUeBmo.t91CmUnRSxRj70drlQwZCQ',
            'expires_in': 3600,
            'token_type': 'Bearer'
        }
        token_resp = json.dumps(token_resp_dict)

        return token_resp, token_resp_dict

    @staticmethod
    def get_decrypted_state_for_new_user():
        """
        Get data for a new user who does not have a GameKit account yet. For example, they haven't registered with
        email and password yet and haven't signed in through an identity provider before (Facebook, etc.).
        """
        state = {
            'request_id': '7b8961cb-19db-47e3-88cb-afcd9884b81d',
            'expiration': 9999999999,
            'source_ip': '12.123.123.12'
        }
        return json.dumps(state).encode('utf-8')

    @staticmethod
    def get_decrypted_state_for_existing_user():
        """
        Get data for a returning user who already has a GameKit account. For example, they've already registered with
        email and password or have already signed in through a different identity provider (ex: Facebook.).
        """
        state = {
            'request_id': '7b8961cb-19db-47e3-88cb-afcd9884b81d',
            'expiration': 9999999999,
            'source_ip': '12.123.123.12',
            'gk_user_id': '0d386660-8f62-4da7-b31c-43ab1237c540',
            'gk_user_id_hash': 'nnk9/21CoT8BEmWT7o/XZPtb7FJPdXFC5hUilV7W0fA=',
        }
        return json.dumps(state).encode('utf-8')

    @staticmethod
    def get_cognito_user_info():
        return {
            'Username': 'Facebook_123456789012345',
            'UserAttributes': [
                {
                    'Name': 'sub',
                    'Value': 'abcdefgh-1234-1234-1234-abcdefghijkl'
                },
                {
                    'Name': 'identities',
                    'Value': '[{"userId":"123456789012345","providerName":"Facebook","providerType":"Facebook","issuer":null,"primary":true,"dateCreated":1625782540634}]'
                },
                {
                    'Name': 'email_verified',
                    'Value': 'false'
                }
            ],
            'UserCreateDate': datetime(2021, 7, 8, 22, 15, 40, 640000, tzinfo=tzlocal()),
            'UserLastModifiedDate': datetime(2021, 7, 10, 6, 44, 29, 194000, tzinfo=tzlocal()),
            'Enabled': True,
            'UserStatus': 'EXTERNAL_PROVIDER',
            'ResponseMetadata': {
                'RequestId': '97c15be8-3951-4e97-a4ce-779e8de762ad',
                'HTTPStatusCode': 200,
                'HTTPHeaders': {
                    'date': 'Sat, 10 Jul 2021 06:57:38 GMT',
                    'content-type': 'application/x-amz-json-1.1',
                    'content-length': '473',
                    'connection': 'keep-alive',
                    'x-amzn-requestid': '97c15be8-3951-4e97-a4ce-779e8de762ad'
                },
                'RetryAttempts': 0
            }
        }

    @staticmethod
    def get_dynamodb_query_response():
        return {
            # No records found:
            'Items': [],
            'Count': 0,
            'ScannedCount': 0,

            # One record found (for future reference):
            # 'Items': [
            #     {
            #         'gk_user_id': {'S': '5bc8a5a0-96ad-4517-b52f-0c6b7180877c'},
            #         'facebook_external_id': {'S': '123456789012345'}
            #     }
            # ],
            # 'Count': 1,
            # 'ScannedCount': 1,

            'ResponseMetadata': {
                'RequestId': 'ELN6BCG2QAVK930L76PBVBB59NVV4KQNSO5AEMVJF66Q9ASUAAJG',
                'HTTPStatusCode': 200,
                'HTTPHeaders': {
                    'server': 'Server',
                    'date': 'Sat, 10 Jul 2021 06:57:38 GMT',
                    'content-type': 'application/x-amz-json-1.0',
                    'content-length': '146',
                    'connection': 'keep-alive',
                    'x-amzn-requestid': 'ELN6BCG2QAVK930L76PBVBB59NVV4KQNSO5AEMVJF66Q9ASUAAJG',
                    'x-amz-crc32': '3550124790'
                },
                'RetryAttempts': 0
            }
        }