from contextlib import asynccontextmanager

from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware

from app.api.v1.router import api_router
from app.config import settings
from app.core.csrf import CSRFProtectionMiddleware
from app.core.error_handlers import SecurityHeadersMiddleware, global_exception_handler, http_exception_handler
from app.core.logging_config import setup_logging
from app.core.middleware import TraceMiddleware
from app.core.monitoring import PerformanceMiddleware, RequestLoggingMiddleware, get_metrics
from app.core.monitoring import init_sentry
from app.core.rate_limiter import RateLimitMiddleware
from app.db import engine
from app.core.logging_config import get_logger

setup_logging()
init_sentry(settings.SENTRY_DSN or None)
logger = get_logger("startup")


@asynccontextmanager
async def lifespan(app: FastAPI):
    # 启动检查：非 DEBUG 模式不能使用默认 JWT_SECRET
    if not settings.DEBUG and settings.JWT_SECRET == "dev-secret-change-in-production":
        import sys
        print("\n" + "=" * 60, file=sys.stderr)
        print("  FATAL: JWT_SECRET is set to the default dev value!", file=sys.stderr)
        print("  Set a secure JWT_SECRET in .env or environment variables.", file=sys.stderr)
        print("=" * 60 + "\n", file=sys.stderr)
        sys.exit(1)
    # SMTP 配置状态检查
    if settings.SMTP_HOST:
        logger.info("SMTP configured: %s:%s → %s", settings.SMTP_HOST, settings.SMTP_PORT, settings.SMTP_FROM)
    else:
        logger.warning("SMTP not configured — emails will be logged, not sent")
    yield
    await engine.dispose()


app = FastAPI(
    title="SciLit Oncology",
    description="肿瘤科文献管理平台",
    version="0.1.0",
    lifespan=lifespan,
    docs_url="/docs" if settings.DEBUG else None,
    redoc_url="/redoc" if settings.DEBUG else None,
    openapi_url="/openapi.json" if settings.DEBUG else None,
)

# 全局异常处理
app.add_exception_handler(Exception, global_exception_handler)
app.add_exception_handler(HTTPException, http_exception_handler)

# 中间件（从内到外）
# CORS: allow_credentials 不能与 allow_origins="*" 同时用，必须明确列出允许的源
app.add_middleware(
    CORSMiddleware,
    allow_origins=settings.CORS_ORIGINS,
    allow_credentials=True,
    allow_methods=["GET", "POST", "PUT", "DELETE", "PATCH"],
    allow_headers=["Authorization", "Content-Type", "X-CSRF-Token", "X-Tenant-Id"],
    expose_headers=["X-Response-Time-Ms", "X-RateLimit-Remaining", "X-RateLimit-Limit"],
)
app.add_middleware(RateLimitMiddleware)
app.add_middleware(PerformanceMiddleware)
app.add_middleware(SecurityHeadersMiddleware)
app.add_middleware(CSRFProtectionMiddleware)
app.add_middleware(RequestLoggingMiddleware)
app.add_middleware(TraceMiddleware)

app.include_router(api_router, prefix=settings.API_V1_PREFIX)


@app.get("/health")
async def health():
    db_ok = False
    try:
        from sqlalchemy import text
        async with engine.begin() as conn:
            await conn.execute(text("SELECT 1"))
        db_ok = True
    except Exception:
        import logging
        logging.getLogger(__name__).warning("Health check DB connection failed")
    return {"status": "ok" if db_ok else "degraded", "specialty": settings.SPECIALTY, "db": "ok" if db_ok else "error", "version": "0.1.0"}


@app.get("/health/metrics")
async def health_metrics():
    """监控指标端点"""
    db_ok = False
    try:
        from sqlalchemy import text
        async with engine.begin() as conn:
            await conn.execute(text("SELECT 1"))
        db_ok = True
    except Exception:
        import logging
        logging.getLogger(__name__).warning("Health metrics DB connection failed")
    return {
        "db": "ok" if db_ok else "error",
        "alerts": get_metrics(),
        "ws": {"online_users": 0, "online_connections": 0},
    }
