"""Factory for creating FastAPI applications with consistent setup."""

# FILE: libs/app_factory.py

from collections.abc import AsyncIterator
from contextlib import asynccontextmanager
from typing import Any

from fastapi import FastAPI, HTTPException, Request
from fastapi.responses import JSONResponse

from libs.config import BaseAppSettings, get_default_settings
from libs.observability import setup_observability
from libs.schemas import ErrorResponse
from libs.security import get_current_user, get_tenant_id
from libs.security.middleware import TrustedProxyMiddleware


def create_trusted_proxy_middleware(
    internal_cidrs: list[str], disable_auth: bool = False
) -> TrustedProxyMiddleware:
    """Create a TrustedProxyMiddleware instance with the given internal CIDRs."""

    # This is a factory function that will be called by FastAPI's add_middleware
    # We return a partial function that creates the middleware
    def middleware_factory(app: Any) -> TrustedProxyMiddleware:
        return TrustedProxyMiddleware(app, internal_cidrs, disable_auth)

    return middleware_factory  # type: ignore


def create_app(  # pylint: disable=too-many-arguments,too-many-positional-arguments
    service_name: str,
    title: str,
    description: str,
    version: str = "1.0.0",
    settings_class: type[BaseAppSettings] = BaseAppSettings,
    custom_settings: dict[str, Any] | None = None,
) -> tuple[FastAPI, BaseAppSettings]:
    """Create a FastAPI application with standard configuration"""

    # Create settings
    settings_kwargs = {"service_name": service_name}
    if custom_settings:
        settings_kwargs.update(custom_settings)

    settings = get_default_settings(**settings_kwargs)
    if settings_class != BaseAppSettings:
        # Use custom settings class
        settings = settings_class(**settings_kwargs)  # type: ignore

    # Create lifespan context manager
    @asynccontextmanager
    async def lifespan(
        app: FastAPI,
    ) -> AsyncIterator[None]:  # pylint: disable=unused-argument
        # Startup
        setup_observability(settings)
        yield
        # Shutdown

    # Create FastAPI app
    app = FastAPI(
        title=title, description=description, version=version, lifespan=lifespan
    )

    # Add middleware
    app.add_middleware(
        TrustedProxyMiddleware,
        internal_cidrs=settings.internal_cidrs,
        disable_auth=getattr(settings, "disable_auth", False),
    )

    # Add exception handlers
    @app.exception_handler(HTTPException)
    async def http_exception_handler(
        request: Request, exc: HTTPException
    ) -> JSONResponse:
        """Handle HTTP exceptions with RFC7807 format"""
        return JSONResponse(
            status_code=exc.status_code,
            content=ErrorResponse(
                type=f"https://httpstatuses.com/{exc.status_code}",
                title=exc.detail,
                status=exc.status_code,
                detail=exc.detail,
                instance=str(request.url),
                trace_id=getattr(request.state, "trace_id", None),
            ).model_dump(),
        )

    # Add health endpoints
    @app.get("/healthz")
    async def health_check() -> dict[str, str]:
        """Health check endpoint"""
        return {
            "status": "healthy",
            "service": settings.service_name,
            "version": version,
        }

    @app.get("/readyz")
    async def readiness_check() -> dict[str, str]:
        """Readiness check endpoint"""
        return {"status": "ready", "service": settings.service_name, "version": version}

    @app.get("/livez")
    async def liveness_check() -> dict[str, str]:
        """Liveness check endpoint"""
        return {"status": "alive", "service": settings.service_name, "version": version}

    return app, settings


# Dependency factories
def get_user_dependency() -> Any:
    """Get user dependency function"""
    return get_current_user()


def get_tenant_dependency() -> Any:
    """Get tenant dependency function"""
    return get_tenant_id()
