from uuid import UUID

from src.__types.errors import ResourceNotFoundError
from src.__types.index import Client, Distribution, Tenant
from src.infrastructure.repositories.client_tenant_repository import ClientTenantRepository
from src.infrastructure.repositories.pending_client_tenant_repository import PendingClientTenantRepository
from src.infrastructure.repositories.tenant_repository import TenantRepository
from src.logger import logger


class ClientTenantService:
    """ClientTenantに関するサービス"""

    def __init__(
        self,
        client_tenant_repository: ClientTenantRepository,
        pending_client_tenant_repository: PendingClientTenantRepository,
        tenant_repository: TenantRepository,
    ) -> None:
        self.client_tenant_repository = client_tenant_repository
        self.pending_client_tenant_repository = pending_client_tenant_repository
        self.tenant_repository = tenant_repository

    def add(
        self,
        client: Client,
        name: str,
        distribution: Distribution,
        customer_id: str,
        base_url: str | None,
    ) -> Tenant | None:
        """ClientTenantの登録リクエストを受け付ける。

        ClientがClientTenantの登録リクエストを受け付けた際には、該当するTenantが存在しなければCLientTenantではなくPendingClientTenantとして作成する。
        COMPANY AIのテナント発行とClientのTenantの発行を順不同にするための処理。
        """
        try:
            tenant = self.tenant_repository.get_by_customer_id(
                distribution=distribution,
                customer_id=customer_id,
            )
        except ResourceNotFoundError:
            logger.info(
                "pending_client_tenant_registration",
                client_id=client.id,
                tenant_name=name,
                distribution=distribution,
                customer_id=customer_id,
            )
            self.pending_client_tenant_repository.add(
                client_id=client.id,
                name=name,
                distribution=distribution,
                customer_id=customer_id,
                base_url=base_url,
            )
            return None
        logger.info(
            "client_tenant_registration",
            client_id=client.id,
            tenant_id=tenant.id,
            tenant_name=name,
            distribution=distribution,
            customer_id=customer_id,
        )
        self.client_tenant_repository.add(
            tenant_id=tenant.id,
            client_id=client.id,
            name=name,
            distribution=distribution,
            customer_id=customer_id,
            base_url=base_url,
        )
        return tenant

    def transfer(
        self,
        tenant_id: UUID,
        distribution: Distribution,
        customer_id: str,
    ) -> None:
        """PendingClientTenantをClientTenantに移行する。

        移行が完了したPendingClientTenantは不要であるため削除する。
        全てのClientTenantが移行対象ではなく、あくまでもTenant発行前に登録されたClientTenantのみが対象。
        """
        pending_client_tenants = self.pending_client_tenant_repository.find_by_customer_id(
            distribution=distribution,
            customer_id=customer_id,
        )

        for pending_client_tenant in pending_client_tenants:
            logger.info(
                "transfer_pending_client_tenant",
                tenant_id=tenant_id,
                client_id=pending_client_tenant.client_id,
                distribution=distribution,
                customer_id=customer_id,
            )
            self.client_tenant_repository.add(
                tenant_id=tenant_id,
                client_id=pending_client_tenant.client_id,
                name=pending_client_tenant.name,
                distribution=pending_client_tenant.distribution,
                customer_id=pending_client_tenant.customer_id,
                base_url=pending_client_tenant.base_url,
            )
            self.pending_client_tenant_repository.delete(
                client_id=pending_client_tenant.client_id,
                name=pending_client_tenant.name,
            )
