from typing import Any

from fastapi import FastAPI, HTTPException, Request, Response, status
from fastapi.exceptions import RequestValidationError
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
from mangum import Mangum
from mangum.types import LambdaContext, LambdaEvent
from pydantic import ValidationError
from src.__types.error_responses import VALIDATION_FAILED_DETAIL, ErrorResponse
from src.const import MANAGEMENT_API_BASE_RESOURCE
from src.routers.http_errors import request_validation_error_to_invalid_params
from src.routers.management import (
    attentions_router,
    quota_allocations_router,
    quota_router,
    quota_usages_router,
    tenants_router,
    users_batch_router,
    users_router,
)
from src.routers.management.description import ROOT_DESCRIPTION, TAGS
from src.settings import Settings
from src.tracer import tracer

settings = Settings()


app = FastAPI(
    title="AI Unit マネジメント API",
    summary="API for managing AI usage data",
    description=ROOT_DESCRIPTION,
    version="1.0.0",
    docs_url=None,  # セキュリティのため、利用しないドキュメントは非表示
    # RedocのAPIドキュメントでは、openapi_tagsで指定した順序でエンドポイントが表示される
    openapi_tags=TAGS,
    # 共通のレスポンス定義、個別のエンドポイントで上書き可能
    responses={
        status.HTTP_401_UNAUTHORIZED: {
            "description": "認証失敗",
            "model": ErrorResponse,
        },
        status.HTTP_422_UNPROCESSABLE_CONTENT: {
            "description": "バリデーションエラー",
            "model": ErrorResponse,
        },
        status.HTTP_500_INTERNAL_SERVER_ERROR: {
            "description": "サーバーエラー",
            "model": ErrorResponse,
        },
    },
)

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)


@app.exception_handler(RequestValidationError)
@app.exception_handler(ValidationError)
async def request_validation_exception_handler(
    _: Request,
    exc: RequestValidationError | ValidationError,
) -> JSONResponse:
    return JSONResponse(
        status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
        content=ErrorResponse(
            detail=VALIDATION_FAILED_DETAIL,
            invalid_parameters=request_validation_error_to_invalid_params(exc),
        ).model_dump(),
    )


@app.exception_handler(HTTPException)
async def http_exception_handler(
    _: Request,
    exc: HTTPException,
) -> JSONResponse:
    def _is_error_response_payload(detail: object) -> bool:
        """HTTPException の detail が ErrorResponse の構造をしているか"""
        return isinstance(detail, dict) and isinstance(detail.get("detail"), str)

    content = exc.detail if _is_error_response_payload(exc.detail) else {"detail": exc.detail}

    return JSONResponse(
        status_code=exc.status_code,
        content=content,
        headers=exc.headers,
    )


@app.get(
    "/",
    status_code=status.HTTP_200_OK,
    tags=["その他"],
    responses={
        status.HTTP_200_OK: {
            "description": "ヘルスチェック成功",
        },
    },
    summary="ヘルスチェック",
)
async def health_check() -> Response:
    return Response(status_code=status.HTTP_200_OK)


app.include_router(
    quota_usages_router.router,
    prefix=MANAGEMENT_API_BASE_RESOURCE,
)
app.include_router(
    attentions_router.router,
    prefix=MANAGEMENT_API_BASE_RESOURCE,
)
app.include_router(
    quota_router.router,
    prefix=MANAGEMENT_API_BASE_RESOURCE,
)
app.include_router(
    quota_allocations_router.router,
    prefix=MANAGEMENT_API_BASE_RESOURCE,
)
app.include_router(
    users_batch_router.router,
    prefix=MANAGEMENT_API_BASE_RESOURCE,
)
app.include_router(
    users_router.router,
    prefix=MANAGEMENT_API_BASE_RESOURCE,
)
app.include_router(
    tenants_router.router,
    prefix=MANAGEMENT_API_BASE_RESOURCE,
)

mangum = Mangum(app)


@tracer.capture_lambda_handler
def handler(event: LambdaEvent, context: LambdaContext) -> dict[str, Any]:
    return mangum(event, context)
