from src.__types.index import Tenant, UserWriteAttribute
from src.domain.services.user_service import UserService
from src.infrastructure.credential_manager import CredentialManager
from src.infrastructure.repositories.tenant_repository import TenantRepository
from src.logger import logger


class ManagementConsoleService:
    """管理画面の開通に関するサービス"""

    def __init__(
        self,
        tenant_repository: TenantRepository,
        credential_manager: CredentialManager,
        user_service: UserService,
    ) -> None:
        self.tenant_repository = tenant_repository
        self.credential_manager = credential_manager
        self.user_service = user_service

    def initialize(
        self,
        tenant: Tenant,
        tenant_name: str,
        user_emails: list[str],
    ) -> None:
        """管理画面を開通する。

        1. ユーザー認証用クライアントを発行する
        2. 管理画面に必要な情報をDBに登録する
        3. 初期ユーザーを一括追加する
        """
        users = [
            UserWriteAttribute(
                display_id=email.split("@")[0],
                display_name=email.split("@")[0],
                email=email,
            )
            for email in user_emails
        ]

        user_application_client_id = self.credential_manager.issue_user_login(tenant.id)
        try:
            self.tenant_repository.update_name_and_user_application_client_id(
                tenant_id=tenant.id,
                name=tenant_name,
                user_application_client_id=user_application_client_id,
            )
        except Exception:
            self._cleanup_credential(user_application_client_id)
            raise

        try:
            self.user_service.bulk_add(users=users)
        except Exception:
            self._cleanup_tenant(tenant=tenant)
            self._cleanup_credential(user_application_client_id)
            raise

    def _cleanup_tenant(self, tenant: Tenant) -> None:
        """DBに登録したテナント情報を元に戻す。"""
        try:
            self.tenant_repository.update_name_and_user_application_client_id(
                tenant_id=tenant.id,
                name=tenant.name,
                user_application_client_id=tenant.user_application_client_id,
            )
        except Exception:  # noqa: BLE001
            # Why: クリーンアップ失敗時に元の例外が隠れないよう、個別の例外はログに残して握りつぶす。
            logger.exception("Cleanup failed: Could not rollback tenant from DB.", tenant_id=tenant.id)

    def _cleanup_credential(self, application_client_id: str) -> None:
        """登録した資格情報を削除して元の状態に戻す。"""
        try:
            self.credential_manager.delete(application_client_id)
        except Exception:  # noqa: BLE001
            # Why: クリーンアップ失敗時に元の例外が隠れないよう、個別の例外はログに残して握りつぶす。
            logger.exception(
                "Cleanup failed: Could not rollback credential in UserPool.",
                application_client_id=application_client_id,
            )
