from django.utils.deprecation import MiddlewareMixin
from rest_framework.response import Response
from rest_framework.exceptions import APIException, ValidationError
import json

class StandardResponseMiddleware(MiddlewareMixin):
    """
    统一API响应格式的中间件
    
    为所有DRF响应添加标准格式：
    {
        "success": true/false,
        "code": status_code,
        "message": "响应消息",
        "data": response_data
    }
    """
    
    def _extract_validation_error_message(self, data):
        """提取验证错误信息为可读字符串"""
        if not isinstance(data, dict):
            return str(data)
            
        error_messages = []
        for field, errors in data.items():
            if isinstance(errors, list):
                for error in errors:
                    if isinstance(error, dict):
                        # 嵌套错误
                        nested_msg = self._extract_validation_error_message(error)
                        error_messages.append(f"{field}: {nested_msg}")
                    else:
                        # 简单错误
                        error_messages.append(f"{field}: {error}")
            elif isinstance(errors, dict):
                # 嵌套对象错误
                nested_msg = self._extract_validation_error_message(errors)
                error_messages.append(f"{field}: {nested_msg}")
            else:
                # 直接错误
                error_messages.append(f"{field}: {errors}")
                
        return "；".join(error_messages)
    
    def process_response(self, request, response):
        # 排除Swagger文档的响应
        if request.path.startswith('/swagger/') or request.path.startswith('/redoc/'):
            return response
            
        # 只处理REST framework的响应和JSON响应
        if hasattr(response, 'data'):
            # 检查是否已经是标准格式
            if isinstance(response.data, dict) and all(k in response.data for k in ['success', 'code']):
                # 已经是标准格式，无需处理
                return response
                
            # 获取状态码
            status_code = response.status_code
            
            # 判断请求是否成功
            success = 200 <= status_code < 300
            
            # 构建标准响应数据
            standard_data = {
                'success': success,
                'code': status_code,
                'message': ''
            }
            
            # 处理不同类型的响应数据
            if isinstance(response.data, dict):
                # 检查是否为验证错误(状态码400)
                if status_code == 400 and not response.data.get('message') and not response.data.get('detail'):
                    # 尝试从字段错误中提取消息
                    error_message = self._extract_validation_error_message(response.data)
                    if error_message:
                        standard_data['message'] = error_message
                        # 这里可以决定是否保留原始错误数据
                        standard_data['data'] = response.data
                else:
                    # 字典类型的响应
                    message = response.data.get('message', '')
                    if not message and 'detail' in response.data:
                        message = response.data.pop('detail')
                    
                    standard_data['message'] = message
                    
                    # 移除message，避免重复
                    if 'message' in response.data:
                        response.data.pop('message')
                    
                    # 检查是否是分页数据
                    if 'count' in response.data and 'results' in response.data:
                        # 这是分页响应，保留分页信息
                        standard_data['data'] = response.data
                    elif response.data and response.data != {'detail': message}:
                        # 其他字典类型数据
                        standard_data['data'] = response.data
            elif isinstance(response.data, list):
                # 列表类型的响应（如视图集的list方法）
                standard_data['message'] = '获取成功'
                standard_data['data'] = response.data
            else:
                # 其他类型的响应（如字符串、数字等）
                standard_data['message'] = '获取成功'
                standard_data['data'] = response.data
            
            # 更新响应数据
            response.data = standard_data
            
            # 确保content也更新
            try:
                response.content = json.dumps(response.data, ensure_ascii=False, indent=2)
                response['Content-Type'] = 'application/json'
            except:
                pass
                
        return response
    
    def process_exception(self, request, exception):
        # 处理API异常，返回标准格式错误信息
        if isinstance(exception, APIException):
            # 提取详细的错误消息
            message = str(exception)
            data = None
            
            # 如果是验证错误，尝试提取更友好的错误消息
            if isinstance(exception, ValidationError) and isinstance(exception.detail, dict):
                message = self._extract_validation_error_message(exception.detail)
                data = exception.detail
                
            # 构建标准响应
            response_data = {
                'success': False,
                'code': exception.status_code,
                'message': message
            }
            
            # 可选：包含原始的错误详情
            if data:
                response_data['data'] = data
            
            return Response(response_data, status=exception.status_code)
        
        return None 