"""Main FastAPI application."""

from pathlib import Path
from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse, FileResponse
from fastapi.staticfiles import StaticFiles
from slowapi import Limiter, _rate_limit_exceeded_handler
from slowapi.util import get_remote_address
from slowapi.errors import RateLimitExceeded

from src import __version__ as _app_version
from src.utils.config import settings
from src.utils.logging import get_logger

logger = get_logger(__name__)

# Create FastAPI app
app = FastAPI(
    title="AI Chatbot Penetration Testing Framework",
    description="Automated adversarial testing for AI chatbots",
    version=_app_version,
    docs_url="/docs",
    redoc_url="/redoc",
)

# Prometheus Metrics
try:
    from prometheus_fastapi_instrumentator import Instrumentator

    # Instrument FastAPI app with Prometheus metrics
    Instrumentator().instrument(app).expose(
        app, endpoint="/metrics", include_in_schema=False  # Don't show in OpenAPI docs
    )
    logger.info("prometheus_enabled", endpoint="/metrics")
except ImportError:
    logger.warning("prometheus_disabled", reason="prometheus-fastapi-instrumentator not installed")
except Exception as e:
    logger.warning("prometheus_setup_failed", error=str(e))

# CORS Middleware — locked down in production, open in development
_cors_origins = (
    ["*"]
    if settings.is_development
    else [
        f"http://localhost:{settings.api_port}",
        f"http://127.0.0.1:{settings.api_port}",
    ]
)
app.add_middleware(
    CORSMiddleware,
    allow_origins=_cors_origins,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# Rate Limiting
limiter = Limiter(key_func=get_remote_address)
app.state.limiter = limiter
app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)


# Root endpoint
@app.get("/")
async def root():
    """Root endpoint with service information."""
    return {
        "service": "AI Chatbot Penetration Testing Framework",
        "version": _app_version,
        "environment": settings.environment,
        "dashboard": "/dashboard",
        "docs": "/docs",
        "health": "/health",
    }


@app.get("/health")
async def health_check():
    """Health check endpoint."""
    return {"status": "healthy", "environment": settings.environment}


# Include routers
from src.api.routes import websocket, reports, auth  # noqa: E402

app.include_router(auth.router)
app.include_router(websocket.router, prefix="/api/v1/ws")
app.include_router(reports.router)

# Serve dashboard and static files
FRONTEND_DIR = Path(__file__).parent.parent.parent / "frontend"

if FRONTEND_DIR.exists():
    app.mount("/static", StaticFiles(directory=str(FRONTEND_DIR)), name="static")


@app.get("/dashboard")
async def serve_dashboard():
    """Serve the dashboard home page."""
    index = FRONTEND_DIR / "index.html"
    if index.exists():
        return FileResponse(index, media_type="text/html")
    return JSONResponse(status_code=404, content={"error": "Dashboard not found"})


@app.get("/dashboard/live")
async def serve_live_dashboard():
    """Serve the real-time Mission Control dashboard."""
    path = FRONTEND_DIR / "dashboard.html"
    if path.exists():
        return FileResponse(path, media_type="text/html")
    return JSONResponse(status_code=404, content={"error": "Mission Control not found"})


@app.get("/dashboard/session")
async def serve_session_replay():
    """Serve the session replay page."""
    path = FRONTEND_DIR / "session.html"
    if path.exists():
        return FileResponse(path, media_type="text/html")
    return JSONResponse(status_code=404, content={"error": "Session replay not found"})


@app.get("/dashboard/owasp")
async def serve_owasp_report():
    """Serve the OWASP compliance report page."""
    path = FRONTEND_DIR / "owasp_report.html"
    if path.exists():
        return FileResponse(path, media_type="text/html")
    return JSONResponse(status_code=404, content={"error": "OWASP report not found"})


# Global exception handler
@app.exception_handler(Exception)
async def global_exception_handler(request: Request, exc: Exception):
    """Handle uncaught exceptions."""
    logger.error(
        "unhandled_exception",
        path=request.url.path,
        method=request.method,
        error=str(exc),
        exc_info=True,
    )

    return JSONResponse(
        status_code=500,
        content={
            "error": "Internal server error",
            "detail": str(exc) if settings.is_development else "An error occurred",
        },
    )


# Startup event
@app.on_event("startup")
async def startup_event():
    """Run on application startup."""
    logger.info("application_starting", environment=settings.environment, port=settings.api_port)


# Shutdown event
@app.on_event("shutdown")
async def shutdown_event():
    """Run on application shutdown."""
    logger.info("application_shutting_down")


if __name__ == "__main__":
    import uvicorn

    uvicorn.run(
        "src.api.main:app",
        host="0.0.0.0",
        port=settings.api_port,
        reload=settings.is_development,
        log_level=settings.log_level.lower(),
    )
