package com.rj.config;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.multipart.MultipartException;

import jakarta.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

/**
 * 全局异常处理器
 * 用于捕获和处理各种异常，特别是 HttpMediaTypeNotSupportedException
 * 
 * @author Auto Generated
 * @since 2025-11-30
 */
@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {

    @Autowired
    private ObjectMapper objectMapper;

    /**
     * 处理 HttpMediaTypeNotSupportedException 异常
     * 当 Content-Type 不支持时触发，特别是 multipart/form-data 请求使用 @RequestBody 时
     */
    @ExceptionHandler(HttpMediaTypeNotSupportedException.class)
    public ResponseEntity<Map<String, Object>> handleHttpMediaTypeNotSupportedException(
            HttpMediaTypeNotSupportedException ex, 
            HttpServletRequest request,
            WebRequest webRequest) {
        
        Map<String, Object> result = new HashMap<>();
        String contentType = ex.getContentType() != null ? ex.getContentType().toString() : "unknown";
        String dataType = null;
        
        // 尝试从请求参数中提取 dataType
        try {
            // 如果是 multipart/form-data，尝试从 data 参数中提取
            String dataParam = request.getParameter("data");
            if (dataParam != null && !dataParam.trim().isEmpty()) {
                try {
                    Map<String, Object> dataMap = objectMapper.readValue(dataParam, new TypeReference<Map<String, Object>>() {});
                    dataType = (String) dataMap.get("dataType");
                    if (dataType == null || dataType.trim().isEmpty()) {
                        dataType = (String) dataMap.get("pushDataType");
                    }
                } catch (Exception e) {
                    log.debug("无法从 data 参数解析 dataType: {}", e.getMessage());
                }
            }
            
            // 如果 data 参数中没有，尝试直接从请求参数中获取
            if (dataType == null || dataType.trim().isEmpty()) {
                dataType = request.getParameter("dataType");
                if (dataType == null || dataType.trim().isEmpty()) {
                    dataType = request.getParameter("pushDataType");
                }
            }
        } catch (Exception e) {
            log.debug("提取 dataType 时发生异常: {}", e.getMessage());
        }
        
        // 输出错误信息和 dataType 到控制台
        String errorMessage = String.format(
            "HttpMediaTypeNotSupportedException: Content-Type '%s' is not supported. dataType: %s, URI: %s",
            contentType,
            dataType != null ? dataType : "unknown",
            request.getRequestURI()
        );
        
        log.error(errorMessage);
        System.out.println("==========================================");
        System.out.println("ERROR: " + errorMessage);
        System.out.println("Content-Type: " + contentType);
        System.out.println("dataType: " + (dataType != null ? dataType : "unknown"));
        System.out.println("Request URI: " + request.getRequestURI());
        System.out.println("Request Method: " + request.getMethod());
        System.out.println("==========================================");
        
        result.put("success", false);
        result.put("message", "不支持的 Content-Type: " + contentType);
        result.put("error", "HttpMediaTypeNotSupportedException");
        result.put("contentType", contentType);
        result.put("dataType", dataType);
        result.put("uri", request.getRequestURI());
        
        return ResponseEntity.status(HttpStatus.UNSUPPORTED_MEDIA_TYPE).body(result);
    }

    /**
     * 处理 MultipartException 异常
     * 当 multipart 请求解析失败时触发
     */
    @ExceptionHandler(MultipartException.class)
    public ResponseEntity<Map<String, Object>> handleMultipartException(
            MultipartException ex, 
            HttpServletRequest request) {
        
        Map<String, Object> result = new HashMap<>();
        String dataType = null;
        
        // 尝试从请求参数中提取 dataType
        try {
            String dataParam = request.getParameter("data");
            if (dataParam != null && !dataParam.trim().isEmpty()) {
                try {
                    Map<String, Object> dataMap = objectMapper.readValue(dataParam, new TypeReference<Map<String, Object>>() {});
                    dataType = (String) dataMap.get("dataType");
                    if (dataType == null || dataType.trim().isEmpty()) {
                        dataType = (String) dataMap.get("pushDataType");
                    }
                } catch (Exception e) {
                    log.debug("无法从 data 参数解析 dataType: {}", e.getMessage());
                }
            }
            
            if (dataType == null || dataType.trim().isEmpty()) {
                dataType = request.getParameter("dataType");
                if (dataType == null || dataType.trim().isEmpty()) {
                    dataType = request.getParameter("pushDataType");
                }
            }
        } catch (Exception e) {
            log.debug("提取 dataType 时发生异常: {}", e.getMessage());
        }
        
        String errorMessage = String.format(
            "MultipartException: %s. dataType: %s, URI: %s",
            ex.getMessage(),
            dataType != null ? dataType : "unknown",
            request.getRequestURI()
        );
        
        log.error(errorMessage, ex);
        System.out.println("==========================================");
        System.out.println("ERROR: " + errorMessage);
        System.out.println("dataType: " + (dataType != null ? dataType : "unknown"));
        System.out.println("Request URI: " + request.getRequestURI());
        System.out.println("==========================================");
        
        result.put("success", false);
        result.put("message", "Multipart 请求解析失败: " + ex.getMessage());
        result.put("error", "MultipartException");
        result.put("dataType", dataType);
        result.put("uri", request.getRequestURI());
        
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(result);
    }

    /**
     * 处理 HttpMessageNotReadableException 异常
     * 当请求体无法读取时触发
     */
    @ExceptionHandler(HttpMessageNotReadableException.class)
    public ResponseEntity<Map<String, Object>> handleHttpMessageNotReadableException(
            HttpMessageNotReadableException ex, 
            HttpServletRequest request) {
        
        Map<String, Object> result = new HashMap<>();
        String contentType = request.getContentType();
        String dataType = null;
        
        // 尝试从请求参数中提取 dataType
        try {
            String dataParam = request.getParameter("data");
            if (dataParam != null && !dataParam.trim().isEmpty()) {
                try {
                    Map<String, Object> dataMap = objectMapper.readValue(dataParam, new TypeReference<Map<String, Object>>() {});
                    dataType = (String) dataMap.get("dataType");
                    if (dataType == null || dataType.trim().isEmpty()) {
                        dataType = (String) dataMap.get("pushDataType");
                    }
                } catch (Exception e) {
                    log.debug("无法从 data 参数解析 dataType: {}", e.getMessage());
                }
            }
            
            if (dataType == null || dataType.trim().isEmpty()) {
                dataType = request.getParameter("dataType");
                if (dataType == null || dataType.trim().isEmpty()) {
                    dataType = request.getParameter("pushDataType");
                }
            }
        } catch (Exception e) {
            log.debug("提取 dataType 时发生异常: {}", e.getMessage());
        }
        
        String errorMessage = String.format(
            "HttpMessageNotReadableException: %s. Content-Type: %s, dataType: %s, URI: %s",
            ex.getMessage(),
            contentType != null ? contentType : "unknown",
            dataType != null ? dataType : "unknown",
            request.getRequestURI()
        );
        
        log.error(errorMessage, ex);
        System.out.println("==========================================");
        System.out.println("ERROR: " + errorMessage);
        System.out.println("Content-Type: " + (contentType != null ? contentType : "unknown"));
        System.out.println("dataType: " + (dataType != null ? dataType : "unknown"));
        System.out.println("Request URI: " + request.getRequestURI());
        System.out.println("==========================================");
        
        result.put("success", false);
        result.put("message", "请求体无法读取: " + ex.getMessage());
        result.put("error", "HttpMessageNotReadableException");
        result.put("contentType", contentType);
        result.put("dataType", dataType);
        result.put("uri", request.getRequestURI());
        
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(result);
    }
}

