from contextlib import asynccontextmanager

import sentry_sdk
from fastapi import FastAPI, HTTPException, Request
from fastapi.exceptions import RequestValidationError
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
from sentry_sdk.integrations.celery import CeleryIntegration
from sentry_sdk.integrations.fastapi import FastApiIntegration
from sentry_sdk.integrations.pymongo import PyMongoIntegration
from sentry_sdk.integrations.redis import RedisIntegration

from .api.v1.routes_admin import router as admin_router
from .api.v1.routes_admin_production import router as admin_production_router
from .api.v1.routes_auth import router as auth_router
from .api.v1.routes_briefs import router as briefs_router
from .api.v1.routes_clients import router as clients_router
from .api.v1.routes_files import router as files_router
from .api.v1.routes_glossaries import router as glossaries_router
from .api.v1.routes_invitations import org_router as invitations_org_router
from .api.v1.routes_invitations import router as invitations_router
from .api.v1.routes_jobs import router as jobs_router
from .api.v1.routes_language_qc import router as language_qc_router
from .api.v1.routes_organizations import router as organizations_router
from .api.v1.routes_review_notes import router as review_notes_router
from .api.v1.routes_share import router as share_router
from .api.v1.routes_tts import router as tts_router
from .api.v1.routes_vtt_versions import router as vtt_versions_router
from .api.v1.routes_websockets import router as websockets_router
from .core.config import settings
from .core.database import (
    close_mongo_connection,
    connect_to_mongo,
    get_database,
)
from .core.logging import setup_logging
from .core.redis import close_redis_connection, connect_to_redis, get_redis_client
from .core.secrets_config import initialize_config
from .core.seed import seed_default_admin
from .middleware import create_rate_limit_middleware, create_validation_middleware
from .services.language_qc import seed_language_qc_for_job
from .services.websocket import connection_manager
from .telemetry import (
    app_metrics,
)


@asynccontextmanager
async def lifespan(app: FastAPI):
    # Startup
    setup_logging()

    # Initialize configuration with secrets
    if settings.app_env == "prod":
        try:
            await initialize_config()
            print("✅ Configuration initialized with Secret Manager")
        except Exception as e:
            print(f"⚠️  Failed to load secrets from Secret Manager: {e}")
            print("⚠️  Falling back to environment variables")

    # Initialize Sentry error tracking
    if settings.sentry_dsn and settings.sentry_dsn.startswith(('http', 'https')):
        sentry_sdk.init(
            dsn=settings.sentry_dsn,
            integrations=[
                FastApiIntegration(),
                RedisIntegration(),
                PyMongoIntegration(),
                CeleryIntegration(monitor_beat_tasks=True),
            ],
            traces_sample_rate=0.1 if settings.app_env == "prod" else 1.0,
            environment=settings.app_env,
            release="1.0.0",
            attach_stacktrace=True,
            send_default_pii=False,  # Don't send PII for privacy
        )

    # Initialize telemetry (disabled for local development)
    # setup_tracing("accessible-video-api", "1.0.0")
    # instrument_dependencies()

    # Start Prometheus metrics server in production
    if settings.app_env == "prod":
        app_metrics.start_prometheus_server(port=8001)

    await connect_to_mongo()
    await connect_to_redis()

    try:
        db = await get_database()
        await seed_default_admin(db)
    except Exception as e:
        print(f"⚠️  Could not seed default admin: {e}")
    # await create_indexes()  # Temporarily disabled for debugging

    # T-16: Seed language_qc only for jobs that still lack it (idempotent, skips on subsequent starts)
    try:
        db = await get_database()
        pending_count = await db.jobs.count_documents({"language_qc": {"$exists": False}})
        if pending_count > 0:
            async for job_doc in db.jobs.find(
                {"language_qc": {"$exists": False}},
                {"_id": 1, "status": 1, "outputs": 1, "source": 1, "review": 1, "updated_at": 1, "requested_outputs": 1},
            ):
                await seed_language_qc_for_job(db, job_doc)
            print(f"✅ language_qc migration complete ({pending_count} jobs seeded)")
    except Exception as e:
        print(f"⚠️  language_qc migration failed: {e}")

    # Start WebSocket connection manager
    await connection_manager.start()

    # Initialize middleware with Redis client
    redis_client = get_redis_client()
    if redis_client:
        rate_limit_middleware = await create_rate_limit_middleware(redis_client)
        validation_middleware = await create_validation_middleware()

        # Store middleware in app state for access
        app.state.rate_limit_middleware = rate_limit_middleware
        app.state.validation_middleware = validation_middleware
    elif settings.redis_url:
        # T-13: REDIS_URL is configured but client unavailable — rate limiting is disabled
        print(f"⚠️  Redis configured at {settings.redis_url!r} but connection failed — rate limiting disabled")

    yield
    # Shutdown
    await connection_manager.stop()
    await close_mongo_connection()
    await close_redis_connection()


app = FastAPI(
    title="Accessible Video API",
    description="API for accessible video processing platform",
    version="1.0.0",
    lifespan=lifespan,
)

# CORS middleware
app.add_middleware(
    CORSMiddleware,
    allow_origins=settings.cors_origins_list,
    allow_credentials=True,
    allow_methods=["GET", "POST", "PUT", "PATCH", "DELETE"],
    allow_headers=["*"],
)

# Custom CORS error handler middleware to ensure CORS headers are added to all error responses
# This must be added BEFORE CORSMiddleware (which will be applied after due to reverse order)
@app.middleware("http")
async def cors_error_handler(request, call_next):
    """Ensure CORS headers are added to all responses, including errors."""
    try:
        response = await call_next(request)
    except Exception as e:
        import traceback

        from .core.logging import get_logger as _get_logger
        _get_logger(__name__).exception("🚨 CORS middleware caught: %s\n%s", e, traceback.format_exc())

        from fastapi.responses import JSONResponse
        response = JSONResponse(
            status_code=500,
            content={"detail": "Internal server error"},
        )

    # Always add CORS headers for allowed origins
    origin = request.headers.get("origin")
    if origin and origin in settings.cors_origins_list:
        response.headers["access-control-allow-origin"] = origin
        response.headers["access-control-allow-credentials"] = "true"
        # Add other necessary CORS headers for error responses
        if response.status_code >= 400:
            response.headers["access-control-allow-methods"] = "GET, POST, PUT, PATCH, DELETE"
            response.headers["access-control-allow-headers"] = "*"

    return response

# Global exception handler to ensure CORS headers on all errors
@app.exception_handler(HTTPException)
async def http_exception_handler(request: Request, exc: HTTPException):
    """Handle HTTP exceptions with CORS headers"""
    response = JSONResponse(
        status_code=exc.status_code,
        content={"detail": exc.detail}
    )

    # Add CORS headers
    origin = request.headers.get("origin")
    if origin and origin in settings.cors_origins_list:
        response.headers["access-control-allow-origin"] = origin
        response.headers["access-control-allow-credentials"] = "true"
        response.headers["access-control-allow-methods"] = "GET, POST, PUT, PATCH, DELETE"
        response.headers["access-control-allow-headers"] = "*"

    return response

# Global exception handler for validation errors
@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request: Request, exc: RequestValidationError):
    """Handle request validation errors with CORS headers"""
    response = JSONResponse(
        status_code=422,
        content={"detail": exc.errors(), "body": exc.body}
    )

    # Add CORS headers
    origin = request.headers.get("origin")
    if origin and origin in settings.cors_origins_list:
        response.headers["access-control-allow-origin"] = origin
        response.headers["access-control-allow-credentials"] = "true"
        response.headers["access-control-allow-methods"] = "GET, POST, PUT, PATCH, DELETE"
        response.headers["access-control-allow-headers"] = "*"

    return response

# Global exception handler for all other exceptions
@app.exception_handler(Exception)
async def general_exception_handler(request: Request, exc: Exception):
    """Handle all uncaught exceptions with logging"""
    import traceback

    from .core.logging import get_logger

    logger = get_logger(__name__)
    logger.exception(
        "🚨 Unhandled %s %s: %s\n%s",
        request.method, request.url.path, exc, traceback.format_exc(),
    )

    response = JSONResponse(
        status_code=500,
        content={"detail": "Internal server error"},
    )

    # Add CORS headers
    origin = request.headers.get("origin")
    if origin and origin in settings.cors_origins_list:
        response.headers["access-control-allow-origin"] = origin
        response.headers["access-control-allow-credentials"] = "true"

    return response

# Add custom middleware (order matters - applied in reverse order)
@app.middleware("http")
async def rate_limiting_middleware(request, call_next):
    """Apply rate limiting middleware."""
    if hasattr(app.state, 'rate_limit_middleware'):
        return await app.state.rate_limit_middleware(request, call_next)
    return await call_next(request)

@app.middleware("http")
async def validation_middleware(request, call_next):
    """Apply request validation middleware."""
    if request.url.path in ["/health", "/metrics", "/api/v1/auth/login", "/api/v1/auth/refresh"]:
        return await call_next(request)
    if hasattr(app.state, 'validation_middleware'):
        return await app.state.validation_middleware(request, call_next)
    return await call_next(request)

# Instrument FastAPI app for tracing (disabled for local development)
# instrument_fastapi_app(app)

# Include routers
app.include_router(auth_router, prefix="/api/v1")
app.include_router(clients_router, prefix="/api/v1")
app.include_router(organizations_router, prefix="/api/v1")
app.include_router(invitations_org_router, prefix="/api/v1")
app.include_router(invitations_router, prefix="/api/v1")
app.include_router(files_router, prefix="/api/v1")
app.include_router(jobs_router, prefix="/api/v1")
app.include_router(review_notes_router, prefix="/api/v1")
app.include_router(vtt_versions_router, prefix="/api/v1")
app.include_router(language_qc_router, prefix="/api/v1")
app.include_router(glossaries_router, prefix="/api/v1")
app.include_router(tts_router, prefix="/api/v1")
app.include_router(admin_router, prefix="/api/v1")
app.include_router(admin_production_router, prefix="/api/v1")
app.include_router(briefs_router, prefix="/api/v1")
app.include_router(share_router, prefix="/api/v1")
app.include_router(websockets_router, prefix="/api/v1")


@app.get("/health")
async def health_check():
    return {"status": "healthy", "version": "1.0.0"}


@app.get("/metrics")
async def metrics():
    """Prometheus metrics endpoint"""
    from fastapi import Response
    from prometheus_client import CONTENT_TYPE_LATEST, generate_latest

    return Response(
        content=generate_latest(),
        media_type=CONTENT_TYPE_LATEST
    )
