"""全局错误处理 + CSP 安全头中间件"""

from fastapi import HTTPException, Request
from fastapi.responses import JSONResponse
from starlette.middleware.base import BaseHTTPMiddleware

from app.config import settings
from app.core.i18n import detect_language, translate
from app.core.logging_config import get_logger

logger = get_logger("scilit.error")


async def global_exception_handler(request: Request, exc: Exception):
    """捕获所有未处理异常，记录日志后返回统一 JSON"""
    logger.exception(f"Unhandled exception: {request.method} {request.url.path}")
    # Sentry 上报
    try:
        import sentry_sdk
        sentry_sdk.capture_exception(exc)
    except ImportError:
        pass
    lang = detect_language(request.headers.get("accept-language"))
    return JSONResponse(
        status_code=500,
        content={"success": False, "error": {"code": "INTERNAL_ERROR", "message": translate("An unexpected error occurred", lang)}},
    )


async def http_exception_handler(request: Request, exc: HTTPException):
    """统一 HTTPException 返回格式，根据请求语言翻译 detail"""
    lang = detect_language(request.headers.get("accept-language"))
    return JSONResponse(
        status_code=exc.status_code,
        content={"success": False, "error": {"code": f"HTTP_{exc.status_code}", "message": translate(exc.detail, lang)}},
    )


class SecurityHeadersMiddleware(BaseHTTPMiddleware):
    """注入安全头：CSP, X-Frame-Options 等"""

    async def dispatch(self, request: Request, call_next):
        response = await call_next(request)
        response.headers["X-Content-Type-Options"] = "nosniff"
        response.headers["X-Frame-Options"] = "DENY"
        response.headers["X-XSS-Protection"] = "1; mode=block"
        response.headers["Referrer-Policy"] = "strict-origin-when-cross-origin"
        response.headers["Permissions-Policy"] = "camera=(), microphone=(), geolocation=()"
        # 生产环境启用 HSTS（强制 HTTPS，预载 + 子域名）
        if not settings.DEBUG:
            response.headers["Strict-Transport-Security"] = "max-age=31536000; includeSubDomains; preload"
        # CSP 统一在 nginx 层设置
        return response
