"""
FastAPI Application Entry Point
"""
import logging
from pathlib import Path
from contextlib import asynccontextmanager
from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles
from fastapi.exceptions import HTTPException, RequestValidationError
from starlette.middleware.base import BaseHTTPMiddleware
from src.core.config import settings
from src.core.router import include_routers
from src.core.database import register_models
from src.middleware.errors import (
    api_exception_handler,
    http_exception_handler, 
    validation_error_handler,
    general_exception_handler
)
from src.core.exceptions import APIException
from src.middleware.logging import LoggingMiddleware
from src.middleware.security import SecurityMiddleware
from src.middleware.response import CommonResponseMiddleware
from src.apps.files.helper.io import create_uploads_directory

# Configure logging
logging.basicConfig(
    level=getattr(logging, settings.LOG_LEVEL),
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
# Set this for SQLAlchemy logs
logging.getLogger('sqlalchemy.engine').setLevel(logging.INFO)
logger = logging.getLogger(__name__)

# Register Database Models for Alembic
try:
    register_models()
    logging.info("Database models registered successfully")
except Exception as e:
    logging.error(f"Error registering database models: {e}")
    raise

# Import Celery instance (for application initialization)
try:
    from src.worker.celery_app import celery_app
    logger.info("Celery integration initialized")
except ImportError:
    celery_app = None
    logger.warning("Celery not available - background tasks will be disabled")


@asynccontextmanager
async def lifespan(app: FastAPI):
    """Application lifespan management"""
    # Startup
    logger.info("*******FastAPI APPLICATION STARTED*******")
    logger.info(f"Environment: {settings.APP_ENV}")
    logger.info(f"Debug Mode: {settings.APP_DEBUG}")
    
    # Create necessary directories
    create_uploads_directory()
    
    yield
    
    # Shutdown
    logger.info("*******FastAPI APPLICATION STOPPED*******")


# Create FastAPI application
app = FastAPI(
    title=settings.APP_NAME,
    description="A production-ready FastAPI application template with Celery background tasks",
    version=settings.APP_VERSION,
    debug=settings.APP_DEBUG,
    docs_url="/api/docs",
    redoc_url="/api/redoc",
    lifespan=lifespan
)

# CORS Configuration
origins = settings.ALLOWED_ORIGINS

# Define regex for subdomains based on environment
origin_regex = None
if settings.APP_ENV == "dev":
    origin_regex = r"https?://.*\.localhost\.com"
elif settings.APP_ENV == "prod":
    origin_regex = r"https?://.*\.yourdomain\.com"  # Update with your domain

# Add CORS middleware
app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_origin_regex=origin_regex,
    allow_credentials=True,
    allow_methods=settings.ALLOWED_METHODS,
    allow_headers=settings.ALLOWED_HEADERS,
)

# Security middleware as HTTP middleware (executed first)
@app.middleware("http")
async def security_middleware_wrapper(request: Request, call_next):
    security_middleware = SecurityMiddleware(request.app)
    response = await security_middleware.dispatch(request, call_next)
    return response

# Add other middleware (order matters - last added is executed first)
# Response formatting middleware
app.add_middleware(CommonResponseMiddleware)

# Logging middleware (should be last to capture all requests)
app.add_middleware(LoggingMiddleware)

# Exception handlers
app.add_exception_handler(APIException, api_exception_handler)
app.add_exception_handler(HTTPException, http_exception_handler)
app.add_exception_handler(RequestValidationError, validation_error_handler)
app.add_exception_handler(Exception, general_exception_handler)

# Include all application routers
include_routers(app)

# Static files for uploads
create_uploads_directory()
app.mount(
    "/uploads",
    StaticFiles(directory=settings.UPLOADS_DIR),
    name="uploads"
)

if __name__ == "__main__":
    import uvicorn
    
    uvicorn.run(
        "src.main:app",
        host=settings.APP_HOST,
        port=settings.APP_PORT,
        reload=settings.APP_DEBUG,
        log_level=settings.LOG_LEVEL.lower()
    )
