from psycopg import Connection
from pydantic import BaseModel
from src.__types.index import Client, ClientTenantStatus, Distribution, Tenant
from src.domain.services.client_tenant_service import ClientTenantService
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


class ClientTenantListItem(BaseModel):
    name: str
    status: ClientTenantStatus


class ClientTenantUseCase:
    def __init__(
        self,
        client_tenant_repository: ClientTenantRepository,
        pending_client_tenant_repository: PendingClientTenantRepository,
        client_tenant_service: ClientTenantService,
    ) -> None:
        self.client_tenant_repository = client_tenant_repository
        self.pending_client_tenant_repository = pending_client_tenant_repository
        self.client_tenant_service = client_tenant_service

    @classmethod
    def create(cls, connection: Connection) -> "ClientTenantUseCase":
        client_tenant_repository = ClientTenantRepository(connection=connection)
        pending_client_tenant_repository = PendingClientTenantRepository(connection=connection)
        return ClientTenantUseCase(
            client_tenant_repository=client_tenant_repository,
            pending_client_tenant_repository=pending_client_tenant_repository,
            client_tenant_service=ClientTenantService(
                client_tenant_repository=client_tenant_repository,
                pending_client_tenant_repository=pending_client_tenant_repository,
                tenant_repository=TenantRepository(connection=connection),
            ),
        )

    def get(self, client: Client) -> list[ClientTenantListItem]:
        """Clientが解決できるClientTenantの一覧を取得する。"""
        client_tenants = [
            ClientTenantListItem(name=client_tenant.name, status=ClientTenantStatus.ACTIVE)
            for client_tenant in self.client_tenant_repository.find(client_id=client.id)
        ]
        pending_client_tenants = [
            ClientTenantListItem(name=pending_client_tenant.name, status=ClientTenantStatus.PENDING)
            for pending_client_tenant in self.pending_client_tenant_repository.find(client_id=client.id)
        ]
        return sorted(
            client_tenants + pending_client_tenants,
            key=lambda client_tenant: (client_tenant.name, client_tenant.status),
        )

    def add(
        self,
        client: Client,
        name: str,
        distribution: Distribution,
        customer_id: str,
        base_url: str | None,
    ) -> Tenant | None:
        """ClientTenantを追加し、ClientTenantが紐づくTenantを返す。"""
        return self.client_tenant_service.add(
            client=client,
            name=name,
            distribution=distribution,
            customer_id=customer_id,
            base_url=base_url,
        )
