"""
FastAPI Application Entry Point
Transporter Management Backend API
"""
from contextlib import asynccontextmanager
from pathlib import Path
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.middleware.gzip import GZipMiddleware
from fastapi.responses import JSONResponse, RedirectResponse
import logging

from app.config import settings
from app.database import init_db, close_db
from app.routes import api_router
from app.middleware.error_handler import setup_exception_handlers
from app.middleware.rate_limiter import setup_rate_limiting


# Configure logging
logging.basicConfig(
    level=getattr(logging, settings.log_level.upper()),
    format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
)
logger = logging.getLogger(__name__)


@asynccontextmanager
async def lifespan(app: FastAPI):
    """
    Application lifespan manager.
    Handles startup and shutdown events.
    """
    # Startup
    logger.info(f"Starting {settings.app_name} v{settings.app_version}")
    logger.info(f"Environment: {settings.environment}")
    
    # Initialize database (creates tables if needed)
    if settings.environment == "development":
        await init_db()
        logger.info("Database initialized")
    
    yield
    
    # Shutdown
    logger.info("Shutting down application...")
    await close_db()
    logger.info("Database connections closed")


def create_application() -> FastAPI:
    """Create and configure FastAPI application"""
    
    app = FastAPI(
        title=settings.app_name,
        version=settings.app_version,
        description="""
        ## Transporter Management API
        
        A production-ready FastAPI backend for ride-hailing applications.
        
        ### Features
        - 🔐 JWT Authentication with OTP verification
        - 🚗 Ride booking with fare bidding
        - 📍 Real-time location tracking
        - 💳 Wallet and payment management
        - 🗺️ Configurable map providers (Mapbox, Google Maps)
        - 📊 Admin dashboard and analytics
        
        ### API Sections
        - **Auth**: User registration, login, OTP verification
        - **Passenger**: Passenger profile and ride management
        - **Driver**: Driver profile, location, earnings
        - **Rides**: Booking, fare estimation, bidding
        - **Payments**: Wallet, transactions, withdrawals
        - **Admin**: Dashboard, user management, configuration
        - **WebSocket**: Real-time tracking and notifications
        """,
        docs_url="/docs" if (settings.debug or settings.environment == "development") else None,
        redoc_url="/redoc" if (settings.debug or settings.environment == "development") else None,
        openapi_url=f"{settings.api_v1_prefix}/openapi.json",
        swagger_ui_parameters={"persistAuthorization": True},
        lifespan=lifespan,
    )
    
    # Add CORS middleware
    cors_kw = dict(
        allow_origins=list(settings.cors_origins),
        allow_credentials=settings.cors_allow_credentials,
        allow_methods=["*"],
        allow_headers=["*"],
    )
    if settings.environment == "development" or settings.debug:
        # Default cors_origins only lists :3000 / :8080. Mobile + LAN + other dev servers
        # (e.g. http://192.168.x.x:PORT, Vite :5173) need this or the browser shows "Failed to fetch".
        cors_kw["allow_origin_regex"] = (
            r"^https?://("
            r"localhost|127\.0\.0\.1"
            r"|192\.168\.\d{1,3}\.\d{1,3}"
            r"|10\.\d{1,3}\.\d{1,3}\.\d{1,3}"
            r"|172\.(1[6-9]|2\d|3[0-1])\.\d{1,3}\.\d{1,3}"
            r")(:\d+)?$"
        )
    app.add_middleware(CORSMiddleware, **cors_kw)
    
    # Add GZip compression
    app.add_middleware(GZipMiddleware, minimum_size=1000)
    
    # Setup exception handlers
    setup_exception_handlers(app)
    
    # Setup rate limiting
    setup_rate_limiting(app)
    
    # Include API routes
    app.include_router(api_router, prefix=settings.api_v1_prefix)
    
    # Include Dashboard Router (Admin)
    from app.routes import dashboard
    app.include_router(dashboard.router, prefix=settings.api_v1_prefix)
    
    # Local uploads (profile pictures, etc.)
    from fastapi.staticfiles import StaticFiles
    _root = Path(__file__).resolve().parent.parent
    _uploads = (_root / settings.local_upload_dir.lstrip("./")).resolve()
    _uploads.mkdir(parents=True, exist_ok=True)
    app.mount("/uploads", StaticFiles(directory=str(_uploads)), name="uploads")
    
    # Setup Admin Panel
    # from app.admin import setup_admin
    from app.database import engine
    # setup_admin(app, engine)
    
    # Mount Frontend (Static Files)
    import os
    frontend_path = "frontend"
    if os.path.exists(frontend_path):
        app.mount("/console", StaticFiles(directory=frontend_path, html=True), name="console")
        logger.info(f"Frontend mounted at /console")
    
    # Health check endpoint
    @app.get("/health", tags=["Health"])
    async def health_check():
        """Health check endpoint for load balancers"""
        return JSONResponse(
            content={
                "status": "healthy",
                "app": settings.app_name,
                "version": settings.app_version,
                "environment": settings.environment,
            }
        )
    
    @app.get(f"{settings.api_v1_prefix}/health", tags=["Health"])
    async def api_health_check():
        """API health check endpoint"""
        return {"status": "healthy"}

    @app.get("/")
    async def root():
        """Redirect root to console"""
        return RedirectResponse(url="/console")
    
    return app


# Create application instance
app = create_application()


def custom_openapi():
    """Customize OpenAPI schema for Swagger documentation"""
    if app.openapi_schema:
        return app.openapi_schema
    from fastapi.openapi.utils import get_openapi
    openapi_schema = get_openapi(
        title=app.title,
        version=app.version,
        description=app.description,
        routes=app.routes,
    )
    # Servers for Swagger "Try it out". Relative "/" must be first: otherwise when you open
    # /docs from http://192.168.x.x:8000 (phone / another PC), the default server stays
    # http://localhost:8000 and requests go to the wrong host → "Failed to fetch".
    openapi_schema["servers"] = [
        {"url": "/", "description": "This machine (recommended — uses same host as /docs)"},
        {"url": "http://127.0.0.1:8000", "description": "This computer only (127.0.0.1)"},
        {"url": "http://localhost:8000", "description": "This computer only (localhost)"},
    ]
    # Enhance Bearer auth scheme for Swagger Authorize
    if "components" in openapi_schema and "securitySchemes" in openapi_schema["components"]:
        if "HTTPBearer" in openapi_schema["components"]["securitySchemes"]:
            openapi_schema["components"]["securitySchemes"]["HTTPBearer"]["bearerFormat"] = "JWT"
            openapi_schema["components"]["securitySchemes"]["HTTPBearer"]["description"] = (
                "JWT access token. Obtain from /auth/login or /auth/register."
            )
    app.openapi_schema = openapi_schema
    return app.openapi_schema


app.openapi = custom_openapi


if __name__ == "__main__":
    import uvicorn
    
    uvicorn.run(
        "app.main:app",
        host=settings.host,
        port=settings.port,
        reload=settings.debug,
        workers=1 if settings.debug else settings.workers,
    )
