package com.ruoyi.framework.web.handler;

import java.lang.reflect.Field;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.utils.file.ResourceUrlUtils;

/**
 * 处理Controller返回结果中的资源URL
 */
@ControllerAdvice
public class ResourceUrlResponseBodyAdvice implements ResponseBodyAdvice<Object> {

    private static final String[] RESOURCE_FIELD_NAMES = {
            "avatar", "img", "image", "photo", "pic", "picture", "portrait", "file", "url", "cover", "logo",
            "background", "thumbnail", "audio", "video", "media", "attachment"
    };

    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        // 处理所有Controller返回的结果
        return true;
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
            Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request,
            ServerHttpResponse response) {
        if (body == null) {
            return null;
        }

        // 处理AjaxResult
        if (body instanceof AjaxResult) {
            handleAjaxResult((AjaxResult) body);
        }
        // 处理TableDataInfo
        else if (body instanceof TableDataInfo) {
            handleTableDataInfo((TableDataInfo) body);
        }
        // 处理集合类型
        else if (body instanceof Collection) {
            handleCollection((Collection<?>) body);
        }
        // 处理Map类型
        else if (body instanceof Map) {
            handleMap((Map<?, ?>) body);
        }
        // 处理普通对象
        else {
            handleObject(body);
        }

        return body;
    }

    /**
     * 处理AjaxResult中的资源URL
     */
    private void handleAjaxResult(AjaxResult ajaxResult) {
        // AjaxResult本身就是HashMap的子类
        handleMap(ajaxResult);
    }

    /**
     * 处理TableDataInfo中的资源URL
     */
    private void handleTableDataInfo(TableDataInfo tableDataInfo) {
        List<?> rows = tableDataInfo.getRows();
        handleCollection(rows);
    }

    /**
     * 处理集合中的资源URL
     */
    private void handleCollection(Collection<?> collection) {
        if (collection == null || collection.isEmpty()) {
            return;
        }

        for (Object item : collection) {
            if (item instanceof Map) {
                handleMap((Map<?, ?>) item);
            } else {
                handleObject(item);
            }
        }
    }

    /**
     * 处理Map中的资源URL
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    private void handleMap(Map<?, ?> map) {
        if (map == null || map.isEmpty()) {
            return;
        }

        for (Map.Entry<?, ?> entry : map.entrySet()) {
            String key = entry.getKey() != null ? entry.getKey().toString() : null;
            Object value = entry.getValue();

            // 处理键中包含的资源字段
            if (key != null && isResourceField(key)) {
                if (value instanceof String) {
                    // 使用安全的类型转换
                    ((Map) map).put(entry.getKey(), ResourceUrlUtils.addDomainPrefix((String) value));
                }
            }

            // 处理值中的子对象
            if (value instanceof Map) {
                handleMap((Map<?, ?>) value);
            } else if (value instanceof Collection) {
                handleCollection((Collection<?>) value);
            } else if (value != null && !(value instanceof String) && !(value instanceof Number) && !(value instanceof Boolean)) {
                handleObject(value);
            }
        }
    }

    /**
     * 处理普通对象中的资源URL
     */
    private void handleObject(Object obj) {
        if (obj == null) {
            return;
        }

        Class<?> clazz = obj.getClass();
        // 基本类型、字符串、日期等类型不处理
        if (clazz.isPrimitive() || clazz.getName().startsWith("java.lang") || clazz.getName().startsWith("java.util")
                || clazz.getName().startsWith("java.sql") || clazz.getName().startsWith("java.time")) {
            return;
        }

        try {
            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) {
                field.setAccessible(true);
                String fieldName = field.getName();
                Object fieldValue = field.get(obj);

                // 处理资源字段
                if (isResourceField(fieldName) && fieldValue instanceof String) {
                    String url = (String) fieldValue;
                    field.set(obj, ResourceUrlUtils.addDomainPrefix(url));
                }
                // 处理嵌套对象
                else if (fieldValue instanceof Map) {
                    handleMap((Map<?, ?>) fieldValue);
                } else if (fieldValue instanceof Collection) {
                    handleCollection((Collection<?>) fieldValue);
                } else if (fieldValue != null && !(fieldValue instanceof String) && !(fieldValue instanceof Number)
                        && !(fieldValue instanceof Boolean)) {
                    handleObject(fieldValue);
                }
            }
        } catch (Exception e) {
            // 反射异常，忽略处理
        }
    }

    /**
     * 判断是否为资源字段
     */
    private boolean isResourceField(String fieldName) {
        if (fieldName == null || fieldName.isEmpty()) {
            return false;
        }

        fieldName = fieldName.toLowerCase();
        for (String resourceField : RESOURCE_FIELD_NAMES) {
            if (fieldName.contains(resourceField)) {
                return true;
            }
        }
        return false;
    }
} 