from uuid import UUID

import psycopg
from psycopg.rows import class_row
from src.__types.errors import ResourceDuplicatedError
from src.__types.index import Distribution, PendingClientTenant


class PendingClientTenantRepository:
    """PendingClientTenantを管理するリポジトリ"""

    def __init__(self, connection: psycopg.Connection) -> None:
        self.connection = connection

    def add(
        self,
        client_id: UUID,
        name: str,
        distribution: Distribution,
        customer_id: str,
        base_url: str | None,
    ) -> None:
        """PendingClientTenantを追加する"""
        try:
            with self.connection.cursor() as cur:
                cur.execute(
                    """--sql
                    INSERT INTO pending_client_tenants (
                        client_id,
                        name,
                        distribution,
                        customer_id,
                        base_url
                    )
                    VALUES (
                        %(client_id)s,
                        %(name)s,
                        %(distribution)s,
                        %(customer_id)s,
                        %(base_url)s
                    )
                    """,
                    {
                        "client_id": str(client_id),
                        "name": name,
                        "distribution": distribution.value,
                        "customer_id": customer_id,
                        "base_url": base_url,
                    },
                )
        except psycopg.errors.UniqueViolation as e:
            raise ResourceDuplicatedError(
                f"Pending client tenant with name '{name}' for client ID {client_id} already exists.",
            ) from e

    def find_by_customer_id(
        self,
        distribution: Distribution,
        customer_id: str,
    ) -> list[PendingClientTenant]:
        """該当のcustomer_idを持つPendingClientTenant一覧を取得する"""
        with self.connection.cursor(row_factory=class_row(PendingClientTenant)) as cur:
            cur.execute(
                """--sql
                SELECT client_id, name, distribution, customer_id, base_url
                FROM pending_client_tenants
                WHERE distribution = %(distribution)s
                    AND customer_id = %(customer_id)s
                ORDER BY client_id, name
                """,
                {
                    "distribution": distribution.value,
                    "customer_id": customer_id,
                },
            )
            return list(cur.fetchall())

    def find(self, client_id: UUID) -> list[PendingClientTenant]:
        """client_idが一致するPendingClientTenantの一覧を取得する。"""
        with self.connection.cursor(row_factory=class_row(PendingClientTenant)) as cur:
            cur.execute(
                """--sql
                SELECT client_id, name, distribution, customer_id, base_url
                FROM pending_client_tenants
                WHERE client_id = %(client_id)s
                ORDER BY name
                """,
                {
                    "client_id": str(client_id),
                },
            )
            return list(cur.fetchall())

    def delete(self, client_id: UUID, name: str) -> None:
        """PendingClientTenantを削除する"""
        with self.connection.cursor() as cur:
            cur.execute(
                """--sql
                DELETE FROM pending_client_tenants
                WHERE client_id = %(client_id)s
                    AND name = %(name)s
                """,
                {
                    "client_id": str(client_id),
                    "name": name,
                },
            )
