from unittest.mock import Mock

import pytest
from pytest_mock import MockFixture
from src.__types.errors import AlreadyInitializedError
from src.tools.management_console_initializer import main

TOOL_PATH = "src.tools.management_console_initializer."


class TestManagementConsoleInitializer:
    @pytest.fixture
    def mock_connect(self, mocker: MockFixture) -> Mock:
        mock_connection = mocker.Mock()
        connect_mock = mocker.patch(f"{TOOL_PATH}psycopg.connect")
        connect_mock.return_value.__enter__.return_value = mock_connection
        return connect_mock

    @pytest.fixture
    def mock_settings(self, mocker: MockFixture) -> Mock:
        mock = mocker.patch(f"{TOOL_PATH}settings")
        mock.management_user_pool_id = "pool-id"
        mock.postgres_url = "postgresql://user:pass@localhost:5432/db"
        return mock

    @pytest.mark.usefixtures("mock_connect", "mock_settings")
    class TestMain:
        def test_calls_usecase_initialize(self, mocker: MockFixture) -> None:
            """main関数がusecaseのinitializeを正しい引数で呼び出すことを確認する。"""
            # Arrange
            mock_usecase = mocker.Mock()
            mocker.patch(
                f"{TOOL_PATH}ManagementConsoleUseCase.create",
                return_value=mock_usecase,
            )
            # Act
            main(
                whi_customer_ids=["whi#1"],
                cydas_customer_ids=["cydas#1"],
                tenant_name="テスト管理画面",
                user_emails=["admin@example.com"],
            )

            # Assert
            mock_usecase.initialize.assert_called_once_with(
                whi_customer_ids=["whi#1"],
                cydas_customer_ids=["cydas#1"],
                tenant_name="テスト管理画面",
                user_emails=["admin@example.com"],
            )

        def test_raises_when_already_initialized(self, mocker: MockFixture) -> None:
            """UsecaseでAlreadyInitializedError発生時にエラーがスローされることを確認する。"""
            # Arrange
            mock_usecase = mocker.Mock()
            mock_usecase.initialize.side_effect = AlreadyInitializedError("already initialized")
            mocker.patch(
                f"{TOOL_PATH}ManagementConsoleUseCase.create",
                return_value=mock_usecase,
            )

            # Act & Assert
            with pytest.raises(AlreadyInitializedError, match="already initialized"):
                main(
                    whi_customer_ids=[],
                    cydas_customer_ids=[],
                    tenant_name="テスト",
                    user_emails=["a@b.com"],
                )
