import logging
import time

from fastapi import FastAPI
from fastapi import HTTPException
from fastapi.exceptions import RequestValidationError
from fastapi.encoders import jsonable_encoder
from fastapi.responses import JSONResponse
from starlette import status
from starlette.requests import Request

from app.api.auth import router as auth_router
from app.api.audit import router as audit_router
from app.api.customers import router as customers_router
from app.api.dashboard import router as dashboard_router
from app.api.knowledge import router as knowledge_router
from app.api.permissions import router as permissions_router
from app.api.repairs import router as repairs_router
from app.api.roles import router as roles_router
from app.api.users import router as users_router
from app.db.database import SessionLocal
from app.db.health import check_database
from app.core.logging import configure_logging
from app.knowledge_seed import seed_knowledge_manufacturers
from app.rbac.seed import seed_rbac
from app.services.initial_admin_bootstrap import bootstrap_initial_admin

configure_logging()

app = FastAPI(
    title="Hermes API",
    version="0.1.0",
    description="Backend von Olympus",
)

app.include_router(auth_router)
app.include_router(audit_router)
app.include_router(users_router)
app.include_router(roles_router)
app.include_router(permissions_router)
app.include_router(customers_router)
app.include_router(knowledge_router)
app.include_router(repairs_router)
app.include_router(dashboard_router)

logger = logging.getLogger(__name__)


@app.middleware("http")
async def request_logging_middleware(request: Request, call_next):
    start = time.perf_counter()
    response = await call_next(request)
    duration_ms = round((time.perf_counter() - start) * 1000, 2)
    logger.info(
        "request.completed",
        extra={
            "method": request.method,
            "path": request.url.path,
            "status_code": response.status_code,
            "duration_ms": duration_ms,
        },
    )
    return response


def error_code_for_status(status_code: int) -> str:
    return {
        400: "BAD_REQUEST",
        401: "UNAUTHORIZED",
        403: "FORBIDDEN",
        404: "NOT_FOUND",
        409: "CONFLICT",
        422: "VALIDATION_ERROR",
    }.get(status_code, "HTTP_ERROR")


@app.on_event("startup")
def startup_seed_rbac():
    db = SessionLocal()
    try:
        seed_rbac(db)
        seed_knowledge_manufacturers(db)
        bootstrap_initial_admin(db)
    finally:
        db.close()


@app.exception_handler(HTTPException)
async def http_exception_handler(request: Request, exc: HTTPException):
    logger.warning(
        "http_exception",
        extra={
            "path": request.url.path,
            "method": request.method,
            "status_code": exc.status_code,
        },
    )
    return JSONResponse(
        status_code=exc.status_code,
        content={
            "success": False,
            "message": str(exc.detail),
            "error_code": error_code_for_status(exc.status_code),
            "details": [],
            "detail": exc.detail,
        },
        headers=exc.headers,
    )


@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request: Request, exc: RequestValidationError):
    logger.warning(
        "validation_exception",
        extra={"path": request.url.path, "method": request.method},
    )
    return JSONResponse(
        status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
        content={
            "success": False,
            "message": "Validierung fehlgeschlagen",
            "error_code": "VALIDATION_ERROR",
            "details": jsonable_encoder(exc.errors()),
            "detail": jsonable_encoder(exc.errors()),
        },
    )


@app.exception_handler(Exception)
async def unhandled_exception_handler(request: Request, exc: Exception):
    logger.exception(
        "unhandled_exception",
        extra={"path": request.url.path, "method": request.method},
    )
    return JSONResponse(
        status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
        content={
            "success": False,
            "message": "Interner Serverfehler",
            "error_code": "INTERNAL_SERVER_ERROR",
            "details": [],
            "detail": "Interner Serverfehler",
        },
    )


@app.get("/")
def root():
    return {
        "service": "Hermes",
        "status": "running",
    }


@app.get("/health")
def health():
    return {
        "status": "healthy",
        "database": check_database(),
    }
