import psycopg
from psycopg.rows import class_row
from src.__types.errors import ResourceNotFoundError
from src.domain.entities.client_api_key import ClientApiKey
from src.settings import Settings

settings = Settings()


class ClientApiKeyRepository:
    """ClientのAPIキーを管理するリポジトリ"""

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

    def get(self, key_id: str) -> ClientApiKey:
        """指定されたIDのAPIキーを取得する"""
        with self.connection.cursor(row_factory=class_row(ClientApiKey)) as cur:
            cur.execute(
                """--sql
                SELECT
                    id,
                    client_id,
                    algorithm,
                    hashed_secret,
                    status,
                    expires_at,
                    rotated_at
                FROM
                    client_api_keys
                WHERE
                    id = %(key_id)s
                """,
                {
                    "key_id": key_id,
                },
            )
            if client := cur.fetchone():
                return client

            raise ResourceNotFoundError(f"Client API Key with id {key_id} not found.")

    def add(self, client_api_key: ClientApiKey) -> None:
        """新しいAPIキーを追加する"""
        with self.connection.cursor() as cur:
            cur.execute(
                """--sql
                INSERT INTO client_api_keys (
                    id,
                    client_id,
                    algorithm,
                    hashed_secret,
                    status,
                    expires_at
                )
                VALUES (
                    %(id)s,
                    %(client_id)s,
                    %(algorithm)s,
                    %(hashed_secret)s,
                    %(status)s,
                    %(expires_at)s
                )
                """,
                client_api_key.model_dump(mode="json"),
            )

    def update_for_rotation(self, client_api_key: ClientApiKey) -> None:
        """指定されたAPIキーをローテーション済みに更新する"""
        with self.connection.cursor() as cur:
            cur.execute(
                """--sql
                UPDATE client_api_keys
                SET
                    status = %(status)s,
                    expires_at = %(expires_at)s,
                    rotated_at = %(rotated_at)s,
                    updated_at = timezone('Asia/Tokyo', now())
                WHERE id = %(key_id)s
                """,
                {
                    **client_api_key.model_dump(mode="json"),
                    "key_id": client_api_key.id,
                },
            )
