"""
Custom FastAPI middleware definitions
Auto-generated by RapidKit - Middleware Module

Framework: {{ framework }}
"""

from __future__ import annotations

import time
from collections.abc import Awaitable, Callable
from dataclasses import dataclass, field
from typing import Any, List

from fastapi import FastAPI
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.middleware.cors import CORSMiddleware
from starlette.requests import Request
from starlette.responses import Response


@dataclass
class {{ module_class_name }}Config:
    """Runtime configuration for {{ module_title }}."""

    enabled: bool = True
    cors_enabled: bool = False
    cors_allow_origins: List[str] = field(default_factory=lambda: ["*"])
    cors_allow_methods: List[str] = field(default_factory=lambda: ["*"])
    cors_allow_headers: List[str] = field(default_factory=lambda: ["*"])
    cors_allow_credentials: bool = True
    process_time_header: bool = True
    service_header: bool = True
    service_name: str | None = None
    service_header_name: str = "X-Service"
    custom_headers: bool = True
    custom_header_name: str = "X-Custom-Header"
    custom_header_value: str = "RapidKit"
    metadata: dict[str, Any] = field(default_factory=dict)
    extra_factories: List[Callable[[FastAPI, "{{ module_class_name }}Config"], None]] = field(
        default_factory=list
    )


def build_default_config() -> {{ module_class_name }}Config:
    """Return default configuration payload."""

    return {{ module_class_name }}Config()


class ProcessTimeMiddleware(BaseHTTPMiddleware):
    """Add X-Process-Time header to all responses."""

    async def dispatch(
        self, request: Request, call_next: Callable[[Request], Awaitable[Response]]
    ) -> Response:
        start_time = time.time()
        response = await call_next(request)
        process_time = time.time() - start_time
        response.headers["X-Process-Time"] = f"{process_time:.6f}"
        return response


class ServiceHeaderMiddleware(BaseHTTPMiddleware):
    """Add service identification headers."""

    def __init__(self, app: FastAPI, service_name: str | None = None, header_name: str = "X-Service"):
        super().__init__(app)
        self.header_name = header_name
        self.service_name = service_name or getattr(app, "title", "RapidKit Service")

    async def dispatch(
        self, request: Request, call_next: Callable[[Request], Awaitable[Response]]
    ) -> Response:
        response = await call_next(request)
        response.headers[self.header_name] = self.service_name
        return response


MiddlewareFactory = Callable[[FastAPI, {{ module_class_name }}Config], None]
_FACTORY_REGISTRY: list[MiddlewareFactory] = []


def register_middleware_factory(factory: MiddlewareFactory) -> None:
    """Register an additional middleware factory consumed during setup."""

    _FACTORY_REGISTRY.append(factory)


# <<<inject:middleware-factories>>>


def _apply_builtin_middlewares(app: FastAPI, config: {{ module_class_name }}Config) -> None:
    """Apply built-in middleware based on the provided configuration."""

    if config.cors_enabled:
        app.add_middleware(
            CORSMiddleware,
            allow_origins=config.cors_allow_origins or ["*"],
            allow_methods=config.cors_allow_methods or ["*"],
            allow_headers=config.cors_allow_headers or ["*"],
            allow_credentials=config.cors_allow_credentials,
        )

    if config.process_time_header:
        app.add_middleware(ProcessTimeMiddleware)

    if config.service_header:
        app.add_middleware(
            ServiceHeaderMiddleware,
            service_name=config.service_name,
            header_name=config.service_header_name,
        )

    if config.custom_headers:
        header_name = config.custom_header_name or "X-Custom-Header"
        header_value = config.custom_header_value or "RapidKit"

        @app.middleware("http")
        async def add_custom_header(  # type: ignore[unused-local]
            request: Request,
            call_next: Callable[[Request], Awaitable[Response]],
        ) -> Response:
            response = await call_next(request)
            response.headers[header_name] = header_value
            return response

    # Always add RapidKit signature header
    @app.middleware("http")
    async def add_rapidkit_signature(  # type: ignore[unused-local]
        request: Request,
        call_next: Callable[[Request], Awaitable[Response]],
    ) -> Response:
        response = await call_next(request)
        response.headers["X-Powered-By"] = "RapidKit"
        return response

    # <<<inject:middleware-defaults>>>


def register_middleware(
    app: FastAPI,
    config: {{ module_class_name }}Config | None = None,
) -> {{ module_class_name }}Config:
    """Register project-wide middleware handlers."""

    cfg = config or build_default_config()
    if not cfg.enabled:
        return cfg

    _apply_builtin_middlewares(app, cfg)

    for factory in _FACTORY_REGISTRY:
        factory(app, cfg)

    for factory in cfg.extra_factories:
        factory(app, cfg)

    return cfg
