# 统一错误处理
from fastapi import FastAPI, Request, HTTPException, status
from fastapi.responses import JSONResponse
from fastapi.exceptions import RequestValidationError
from pydantic import ValidationError
from app.core.logging_config import logger

# 错误码定义
ERROR_CODES = {
    # 认证错误 (10-19)
    401: "E00010",  # 未授权
    403: "E00014",  # 禁止访问
    
    # 验证错误 (20-29)
    400: "E00000",  # 请求错误
    422: "E00000",  # 验证错误
    
    # 资源错误 (30-39)
    404: "E00033",  # 资源不存在
    
    # 服务器错误 (50-59)
    500: "E00003",  # 服务器内部错误
}

# 错误信息映射
ERROR_MESSAGES = {
    "E00010": "未登录或登录已过期",
    "E00011": "用户名或密码错误",
    "E00012": "验证码错误",
    "E00014": "无权访问此资源",
    "E00015": "令牌无效或已过期",
    "E00020": "请输入用户名和密码",
    "E00021": "用户名至少 3 个字符",
    "E00022": "密码至少 6 个字符",
    "E00023": "用户名已存在",
    "E00024": "邮箱已被注册",
    "E00030": "藏品名称不能为空",
    "E00031": "藏品名称至少 2 个字符",
    "E00032": "藏品分类不能为空",
    "E00033": "藏品不存在",
    "E00034": "禁止重复：此冠字号已存在",
    "E00035": "成本价格必须>=0",
    "E00036": "目标价格必须>=0",
    "E00037": "发行年份必须是 4 位数字",
    "E00040": "请选择图片文件",
    "E00041": "图片尺寸太小，无法识别",
    "E00042": "OCR 识别失败，请重试",
    "E00050": "仅管理员可访问",
    "E00051": "用户不存在",
    "E00000": "请求失败",
    "E00001": "网络连接失败",
    "E00003": "服务器内部错误",
}

def setup_error_handlers(app: FastAPI):
    """设置全局错误处理器"""
    
    @app.exception_handler(HTTPException)
    async def http_exception_handler(request: Request, exc: HTTPException):
        """处理 HTTP 异常"""
        # 从 detail 中提取错误码
        detail = exc.detail
        error_code = ERROR_CODES.get(exc.status_code, "E00000")
        
        # 如果 detail 已经包含错误码，直接使用
        if isinstance(detail, str) and detail.startswith("E"):
            parts = detail.split(":", 1)
            error_code = parts[0]
            message = parts[1].strip() if len(parts) > 1 else ERROR_MESSAGES.get(error_code, detail)
        else:
            message = ERROR_MESSAGES.get(error_code, detail if isinstance(detail, str) else "请求失败")
        
        return JSONResponse(
            status_code=exc.status_code,
            content={
                "error": {
                    "code": error_code,
                    "message": message,
                    "status": exc.status_code
                }
            }
        )
    
    @app.exception_handler(RequestValidationError)
    async def validation_exception_handler(request: Request, exc: RequestValidationError):
        """处理请求验证错误"""
        errors = exc.errors()
        if errors:
            error = errors[0]
            field = ".".join(str(x) for x in error.get("loc", []))
            msg = error.get("msg", "验证失败")
            
            # 根据字段和消息匹配错误码
            # 先检查请求路径，区分用户接口和藏品接口
            path = request.url.path
            
            if "cost_price" in field or "价格" in msg:
                error_code = "E00035"
                message = "成本价格必须>=0"
            elif "target_price" in field:
                error_code = "E00036"
                message = "目标价格必须>=0"
            elif "issue_year" in field or "年份" in msg:
                error_code = "E00037"
                message = "发行年份必须是 4 位数字"
            elif "name" in field:
                # 根据路径区分用户 name 和藏品 name
                if "/auth/" in path or "/users/" in path or "/admin/users/" in path:
                    error_code = "E00021"
                    message = "用户名至少 3 个字符"
                else:
                    error_code = "E00031"
                    message = "藏品名称至少 2 个字符"
            elif "category" in field:
                error_code = "E00032"
                message = "藏品分类不能为空"
            else:
                error_code = "E00000"
                message = f"{field}: {msg}"
            
            return JSONResponse(
                status_code=422,
                content={
                    "error": {
                        "code": error_code,
                        "message": message,
                        "status": 422,
                        "field": field
                    }
                }
            )
        
        return JSONResponse(
            status_code=422,
            content={
                "error": {
                    "code": "E00000",
                    "message": "验证失败",
                    "status": 422
                }
            }
        )
    
    @app.exception_handler(404)
    async def not_found_handler(request: Request, exc: Exception):
        """处理 404 错误"""
        return JSONResponse(
            status_code=404,
            content={
                "error": {
                    "code": "E00033",
                    "message": "接口不存在",
                    "status": 404
                }
            }
        )
    
    @app.exception_handler(Exception)
    async def general_exception_handler(request: Request, exc: Exception):
        """处理未捕获的异常"""
        import traceback
        error_trace = traceback.format_exc()
        logger.error(f"未捕获异常：{str(exc)}\n{error_trace}")
        
        return JSONResponse(
            status_code=500,
            content={
                "error": {
                    "code": "E00003",
                    "message": "服务器内部错误",
                    "status": 500
                }
            }
        )
