from datetime import datetime
from typing import Annotated

from fastapi import APIRouter, Depends, HTTPException, status
from psycopg import Connection
from pydantic import BaseModel, ConfigDict, Field, field_serializer
from src.__types.errors import ClientError
from src.__types.index import Client
from src.domain.entities.client_api_key import ClientApiKey
from src.routers.client.authorizer import get_client, get_client_api_key
from src.routers.client.connection import get_connection
from src.settings import Settings
from src.usecases.client_api_key_usecase import ClientApiKeyUseCase

settings = Settings()
router = APIRouter(
    prefix="/api-keys",
    tags=["APIキー"],
)


class PostRotateRequest(BaseModel):
    """APIキーローテーションのリクエストモデル"""

    duration_days: int | None = Field(
        ge=1,
        examples=[90],
        description="新規で発行するAPIキーの有効期限。null の場合、無期限で発行します。",
    )


class PostRotateResponse(BaseModel):
    """APIキーローテーションのレスポンスモデル"""

    api_key: str = Field(..., description="新規で発行されたAPIキー")
    expires_at: datetime | None = Field(
        ...,
        description="新規で発行されたAPIキーの有効期限 (YYYY-MM-DD HH:MM:SS 形式)。null の場合は無期限。",
    )
    model_config = ConfigDict(
        json_schema_extra={
            "example": {
                "api_key": "newly_generated_api_key_string",
                "expires_at": "2025-01-01 12:34:56",
            },
        },
    )

    @field_serializer("expires_at")
    def serialize_expires_at(self, value: datetime | None) -> str | None:
        if value is None:
            return None
        return value.strftime("%Y-%m-%d %H:%M:%S")


@router.post(
    "/rotate",
    summary="APIキーのローテーション",
    description="APIキーをローテーション(再発行)します。既存のAPIキーは非推奨となり、7日後に無効化されます。",
    status_code=status.HTTP_200_OK,
    responses={
        status.HTTP_200_OK: {
            "description": "APIキーのローテーションに成功",
        },
        status.HTTP_400_BAD_REQUEST: {
            "description": "すでにローテーションに使用したAPIキーを使用した場合など、不正なリクエスト",
        },
        status.HTTP_401_UNAUTHORIZED: {
            "description": "認証失敗",
        },
        status.HTTP_403_FORBIDDEN: {
            "description": "権限の不足",
        },
        status.HTTP_422_UNPROCESSABLE_CONTENT: {
            "description": "リクエストボディのバリデーションエラー",
        },
        status.HTTP_429_TOO_MANY_REQUESTS: {
            "description": "レートリミットエラー ※ リトライを推奨します。",
        },
        status.HTTP_500_INTERNAL_SERVER_ERROR: {
            "description": "内部エラー ※ AIユニットの障害発生時には機能の利用を続行してください。",
        },
    },
)
async def post_rotate(
    client: Annotated[Client, Depends(get_client)],
    client_api_key: Annotated[ClientApiKey, Depends(get_client_api_key)],
    request: PostRotateRequest,
    connection: Annotated[Connection, Depends(get_connection)],
) -> PostRotateResponse:
    usecase = ClientApiKeyUseCase.create(connection=connection)

    try:
        result = usecase.rotate(
            client=client,
            duration_days=request.duration_days,
            current_key=client_api_key,
        )
    except ClientError as e:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=e.message) from e

    return PostRotateResponse(
        api_key=result.key.get_secret_value(),
        expires_at=result.expires_at,
    )
