"""
自定义异常处理
"""
import os
import traceback
import threading
import requests
from rest_framework.views import exception_handler
from rest_framework.exceptions import AuthenticationFailed as DRFAuthenticationFailed
from rest_framework.exceptions import NotAuthenticated
from rest_framework import status
from rest_framework_simplejwt.exceptions import InvalidToken, AuthenticationFailed as JWTAuthenticationFailed
from utils.response import APIResponse


# Log Center 配置
LOG_CENTER_URL = os.environ.get('LOG_CENTER_URL', 'https://qiyuan-log-center-api.airlabs.art')
LOG_CENTER_ENABLED = os.environ.get('LOG_CENTER_ENABLED', 'true').lower() == 'true'


def report_to_log_center(exc, context):
    """异步上报错误到 Log Center"""
    if not LOG_CENTER_ENABLED:
        return
    
    try:
        # 提取堆栈信息
        tb = traceback.extract_tb(exc.__traceback__) if exc.__traceback__ else []
        last_frame = tb[-1] if tb else None
        
        # 获取请求信息
        request = context.get('request')
        request_path = request.path if request else 'unknown'
        request_method = request.method if request else 'unknown'
        
        payload = {
            "project_id": "rtc_backend",
            "environment": os.environ.get('ENVIRONMENT', 'development'),
            "level": "ERROR",
            "repo_url": "https://gitea.airlabs.art/zyc/rtc_backend.git",
            "error": {
                "type": type(exc).__name__,
                "message": str(exc),
                "file_path": last_frame.filename if last_frame else "unknown",
                "line_number": last_frame.lineno if last_frame else 0,
                "stack_trace": traceback.format_exception(exc) if exc.__traceback__ else [str(exc)]
            },
            "context": {
                "url": request_path,
                "method": request_method,
                "view": str(context.get('view', '')),
            }
        }
        
        # 异步发送，不阻塞响应
        def send_async():
            try:
                requests.post(
                    f"{LOG_CENTER_URL}/api/v1/logs/report",
                    json=payload,
                    timeout=3
                )
            except Exception:
                pass  # 静默失败
        
        thread = threading.Thread(target=send_async)
        thread.daemon = True
        thread.start()
        
    except Exception:
        pass  # 上报失败不影响主业务


class BusinessException(Exception):
    """业务异常"""
    def __init__(self, code=1, message='业务错误', status_code=status.HTTP_400_BAD_REQUEST):
        self.code = code
        self.message = message
        self.status_code = status_code
        super().__init__(message)


class ErrorCode:
    """错误码定义"""
    # 通用错误 1-99
    SUCCESS = 0
    UNKNOWN_ERROR = 1
    PARAM_ERROR = 2
    NOT_FOUND = 3
    PERMISSION_DENIED = 4
    
    # 用户模块 100-199
    USER_NOT_FOUND = 100
    USER_DISABLED = 101
    PHONE_INVALID = 102
    TOKEN_EXPIRED = 103
    SMS_CODE_INVALID = 110
    SMS_CODE_EXPIRED = 111
    SMS_CODE_SEND_LIMIT = 112
    
    # 设备模块 200-299
    DEVICE_NOT_FOUND = 200
    DEVICE_ALREADY_BOUND = 201
    DEVICE_MAC_EXISTS = 202
    DEVICE_SN_INVALID = 203
    ROLE_MEMORY_NOT_FOUND = 204
    ROLE_MEMORY_TYPE_MISMATCH = 205
    ROLE_MEMORY_ALREADY_BOUND = 206
    
    # 智能体模块 300-399
    SPIRIT_NOT_FOUND = 300
    SPIRIT_LIMIT_EXCEEDED = 301
    
    # 批次模块 400-499
    BATCH_NOT_FOUND = 400
    BATCH_SN_EXISTS = 401
    DEVICE_TYPE_NOT_FOUND = 402

    # 管理员模块 500-599
    ADMIN_NOT_FOUND = 500
    ADMIN_PASSWORD_ERROR = 501

    # 故事模块 600-699
    STORY_NOT_FOUND = 600
    SHELF_NOT_FOUND = 601
    SHELF_LOCKED = 602
    POINTS_NOT_ENOUGH = 603
    SHELF_FULL = 604

    # 音乐模块 700-799
    TRACK_NOT_FOUND = 700
    MUSIC_GENERATE_FAILED = 701
    MUSIC_GENERATING = 702
    MUSIC_DEFAULT_UNDELETABLE = 703

    # 吧唧模块 750-799
    BADGE_IMAGE_NOT_FOUND = 750
    BADGE_GENERATE_FAILED = 751

    # 通知模块 800-899
    NOTIFICATION_NOT_FOUND = 800

    # 系统模块 900-999
    FEEDBACK_SUBMIT_FAILED = 900


def custom_exception_handler(exc, context):
    """自定义异常处理器"""
    # 上报到 Log Center (排除业务异常和认证异常，这些是正常业务流程)
    if not isinstance(exc, (BusinessException, DRFAuthenticationFailed, NotAuthenticated, InvalidToken, JWTAuthenticationFailed)):
        report_to_log_center(exc, context)
    
    # 处理业务异常
    if isinstance(exc, BusinessException):
        return APIResponse(
            code=exc.code,
            message=exc.message,
            status_code=exc.status_code
        )
    
    # 调用DRF默认异常处理
    response = exception_handler(exc, context)
    
    if response is not None:
        # 统一格式化DRF异常
        error_message = ''
        if isinstance(response.data, dict):
            if 'detail' in response.data:
                error_message = str(response.data['detail'])
            else:
                # 处理字段验证错误
                errors = []
                for field, messages in response.data.items():
                    if isinstance(messages, list):
                        errors.append(f"{field}: {', '.join(str(m) for m in messages)}")
                    else:
                        errors.append(f"{field}: {messages}")
                error_message = '; '.join(errors)
        else:
            error_message = str(response.data)
        
        return APIResponse(
            code=ErrorCode.UNKNOWN_ERROR,
            message=error_message,
            status_code=response.status_code
        )
    
    # 处理未知异常
    return APIResponse(
        code=ErrorCode.UNKNOWN_ERROR,
        message=str(exc),
        status_code=status.HTTP_500_INTERNAL_SERVER_ERROR
    )
