import uuid
from unittest.mock import Mock

import pytest
import src.contract_pre_token_generation_trigger as trigger
from psycopg import Connection
from pytest_mock import MockFixture


class TestContractPreTokenGenerationTrigger:
    @pytest.fixture
    def connection(self, mocker: MockFixture) -> Mock:
        return mocker.Mock(spec=Connection)

    @pytest.fixture
    def mock_connect(self, mocker: MockFixture, connection: Mock) -> Mock:
        mock_connect = mocker.patch("src.contract_pre_token_generation_trigger.psycopg.connect")
        mock_connect.return_value.__enter__.return_value = connection
        return mock_connect

    def test_handler_success(
        self,
        mocker: MockFixture,
        mock_connect: Mock,
    ) -> None:
        """正常系: contract_provider_id が追加されることを確認する"""
        # Arrange
        contract_provider_id = uuid.uuid4()
        event = {
            "callerContext": {"clientId": "app-client-id"},
        }

        mock_contract_provider = mocker.Mock()
        mock_contract_provider.id = contract_provider_id
        mock_contract_provider_repository = mocker.Mock()
        mock_contract_provider_repository.get_by_application_client_id.return_value = mock_contract_provider
        mock_repository_cls = mocker.patch(
            "src.contract_pre_token_generation_trigger.ContractProviderRepository",
            return_value=mock_contract_provider_repository,
        )

        # Act
        result = trigger.handler(event, mocker.Mock())

        # Assert
        mock_connect.assert_called_once()
        mock_repository_cls.assert_called_once()
        mock_contract_provider_repository.get_by_application_client_id.assert_called_once_with("app-client-id")
        assert result["response"]["claimsAndScopeOverrideDetails"]["accessTokenGeneration"]["claimsToAddOrOverride"][
            "contract_provider_id"
        ] == str(contract_provider_id)

    def test_raises_when_missing_client_id(self, mocker: MockFixture, mock_connect: Mock) -> None:
        """ClientId がない場合に KeyError が発生することを確認する"""
        # Arrange
        event = {
            "callerContext": {},
        }

        # Act / Assert
        with pytest.raises(KeyError, match=r"application_client_id is required in the event request."):
            trigger.handler(event, mocker.Mock())

        mock_connect.assert_called_once()
