#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
错误处理中间件模块
提供全局异常处理和错误响应格式化
"""

from fastapi import Request, HTTPException
from fastapi.responses import JSONResponse
from fastapi.exceptions import RequestValidationError
import traceback

from utils.logger import get_logger
from routes.common_api import format_response
from config.error_messages import VALIDATION_ERROR_MESSAGES, HTTP_ERROR_MESSAGES
from config.settings import settings

# 设置日志
logger = get_logger("middleware.error_handlers")

async def validation_exception_handler(request: Request, exc: RequestValidationError):
    """
    处理验证错误，将错误消息转换为中文，并提供更友好的错误提示
    包括显示具体缺失的字段名称
    """
    errors = exc.errors()
    error_details = []
    missing_fields = []
    
    for error in errors:
        error_type = error.get("type", "")
        loc = error.get("loc", [])
                
        # 获取完整的字段路径，排除body/query等
        if len(loc) > 1 and loc[0] in ["body", "query", "path", "header"]:
            field_path = ".".join(str(item) for item in loc[1:])
        else:
            field_path = ".".join(str(item) for item in loc)
        
        # 获取中文错误消息
        message = VALIDATION_ERROR_MESSAGES.get(error_type, error.get("msg", "验证错误"))
        
        # 替换消息中的参数
        context = error.get("ctx", {})
        for key, value in context.items():
            message = message.replace(f"{{{key}}}", str(value))
        
        # 收集缺失字段
        if error_type == "missing" or error_type == "value_error.missing":
            missing_fields.append(field_path)
        
        error_details.append({
            "field": field_path,
            "message": message,
            "type": error_type
        })
    
    # 构建友好的错误响应
    if missing_fields:
        missing_fields_str = ", ".join(missing_fields)
        error_message = f"缺少必填字段: {missing_fields_str}"
    elif error_details:
        # 提取第一个错误的字段和消息
        first_error = error_details[0]
        error_message = f"参数 '{first_error['field']}' 验证失败: {first_error['message']}"
    else:
        error_message = "参数验证失败"
    
    # 记录参数验证错误，以便同步到主系统
    logger.warning(f"参数验证失败: {error_message} - 请求路径: {request.url.path}")
    
    return JSONResponse(
        status_code=400,
        content={
            "code": 400,
            "message": error_message,
            "data": error_details if len(error_details) > 1 else None
        }
    )

async def http_exception_handler(request: Request, exc: HTTPException):
    """处理HTTP异常，转换为统一的响应格式"""
    status_code = exc.status_code
    # 获取错误消息，优先使用自定义消息，否则使用配置中的错误消息
    message = exc.detail
    if isinstance(message, str) and message == "Not Found":
        message = HTTP_ERROR_MESSAGES.get(status_code, message)
    
    # 记录HTTP错误日志，以便同步到主系统
    if status_code >= 500:
        # 5xx错误记录为ERROR级别
        logger.error(f"HTTP {status_code} 错误: {message} - 请求路径: {request.url.path}")
    elif status_code >= 400:
        # 4xx错误记录为WARNING级别
        logger.warning(f"HTTP {status_code} 警告: {message} - 请求路径: {request.url.path}")
    
    return JSONResponse(
        status_code=status_code,
        content=format_response(
            code=status_code,
            message=message,
            data=None
        )
    )

async def global_exception_handler(request: Request, exc: Exception):
    """处理所有未捕获的异常"""
    logger.error(f"未捕获异常: {str(exc)}")
    logger.error(traceback.format_exc())
    
    return JSONResponse(
        status_code=500,
        content=format_response(
            code=500,
            message="服务器内部错误，请联系管理员",
            data=None if not settings.DEBUG else str(exc)
        )
    )

def register_exception_handlers(app):
    """
    注册所有异常处理器到FastAPI应用
    
    Args:
        app: FastAPI应用实例
    """
    app.exception_handler(RequestValidationError)(validation_exception_handler)
    app.exception_handler(HTTPException)(http_exception_handler)
    app.exception_handler(Exception)(global_exception_handler) 