package shop.alien.store.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import io.swagger.annotations.ApiModelProperty;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Field;
import java.time.LocalDate;
import java.util.*;

/**
 * 操作內容自動生成工具類
 * 用於自動反射對象字段並生成操作描述
 *
 * @author ssk
 * @since 2025-12-09
 */
@Slf4j
public class ContentGeneratorUtil {

    /**
     * 默認排除的字段（這些字段不會出現在操作描述中）
     */
    private static final Set<String> DEFAULT_EXCLUDE_FIELDS = new HashSet<>(Arrays.asList(
            "id", "deleteFlag", "delFlag", "createdTime", "updatedTime",
            "createdUserId", "updatedUserId", "serialVersionUID", "class"
    ));

    /**
     * 字段名到中文名稱的映射（作為備用，如果沒有@ApiModelProperty注解時使用）
     */
    private static final Map<String, String> FIELD_NAME_MAPPING = new HashMap<String, String>() {{
        // 節假日相關
        put("festivalName", "節日名稱");
        put("particularYear", "年份");
        put("festivalDate", "日期");
        put("startTime", "開始時間");
        put("endTime", "結束時間");
        put("openFlag", "啟用狀態");
        
        // 通用字段
        put("name", "名稱");
        put("title", "標題");
        put("status", "狀態");
        put("type", "類型");
        put("description", "描述");
        put("remark", "備註");
        put("phone", "電話");
        put("address", "地址");
        put("email", "郵箱");
        put("price", "價格");
        put("amount", "金額");
        put("count", "數量");
    }};
    
    /**
     * 從實體類的@ApiModelProperty注解中獲取字段的中文名稱
     */
    private static String getFieldChineseName(Class<?> entityClass, String fieldName) {
        if (fieldName == null || entityClass == null) {
            return fieldName;
        }
        
        // 直接從注解讀取
        return getFieldChineseNameFromAnnotation(entityClass, fieldName);
    }
    
    /**
     * 從實體類的@ApiModelProperty注解中獲取字段的中文名稱
     */
    private static String getFieldChineseNameFromAnnotation(Class<?> clazz, String fieldName) {
        if (fieldName == null || clazz == null) {
            return fieldName;
        }
        
        try {
            // 遍歷類及其父類的所有字段
            Class<?> currentClass = clazz;
            while (currentClass != null && !currentClass.equals(Object.class)) {
                try {
                    Field field = currentClass.getDeclaredField(fieldName);
                    // 嘗試從@ApiModelProperty注解中獲取中文名稱
                    ApiModelProperty apiModelProperty = field.getAnnotation(ApiModelProperty.class);
                    if (apiModelProperty != null) {
                        String value = apiModelProperty.value();
                        if (StringUtils.isNotBlank(value)) {
                            return value;
                        }
                    }
                    // 如果找到字段但沒有注解，跳出循環
                    break;
                } catch (NoSuchFieldException e) {
                    // 字段不在當前類中，繼續查找父類
                }
                
                // 繼續處理父類
                currentClass = currentClass.getSuperclass();
            }
        } catch (Exception e) {
            log.debug("從注解讀取字段中文名稱失敗，字段: {}, 類: {}", fieldName, clazz.getName(), e);
        }
        
        // 如果沒有找到注解，返回字段名本身
        return fieldName;
    }

    /**
     * 自動生成操作內容
     * 根據操作類型和對象字段自動生成描述
     *
     * @param operationType 操作類型（新增、修改、刪除等）
     * @param obj           操作對象
     * @param idField       標識字段名（如 "id"）
     * @param nameField     名稱字段名（如 "name" 或 "festivalName"）
     * @return 生成的操作內容
     */
    public static String generateContent(String operationType, Object obj, String idField, String nameField) {
        if (obj == null) {
            return operationType + "操作";
        }

        try {
            // 獲取對象的字段和值
            Map<String, Object> fieldValues = extractFieldValues(obj);
            
            // 獲取標識和名稱
            String idValue = getFieldValueAsString(fieldValues, idField);
            String nameValue = getFieldValueAsString(fieldValues, nameField);

            // 根據操作類型生成不同的描述
            StringBuilder content = new StringBuilder();
            
            // 獲取字段的中文名稱（從實體類的@ApiModelProperty注解中讀取）
            String idFieldChinese = getFieldChineseNameFromAnnotation(obj.getClass(), idField);
            String nameFieldChinese = getFieldChineseNameFromAnnotation(obj.getClass(), nameField);
            
            if ("新增".equals(operationType)) {
                content.append("新增了");
                if (StringUtils.isNotBlank(nameValue)) {
                    content.append(nameValue);
                } else if (StringUtils.isNotBlank(idValue)) {
                    content.append(idFieldChinese).append("為").append(idValue).append("的記錄");
                } else {
                    content.append("記錄");
                }
                
                // 添加主要字段信息（傳入對象以便讀取注解）
                appendMainFields(content, fieldValues, idField, nameField, obj);
                
            } else if ("修改".equals(operationType) || "更新".equals(operationType)) {
                content.append("修改了");
                if (StringUtils.isNotBlank(nameValue)) {
                    content.append(nameValue);
                } else if (StringUtils.isNotBlank(idValue)) {
                    content.append(idFieldChinese).append("為").append(idValue).append("的記錄");
                } else {
                    content.append("記錄");
                }
                
                // 添加修改的字段信息（傳入對象以便讀取注解）
                appendMainFields(content, fieldValues, idField, nameField, obj);
                
            } else if ("刪除".equals(operationType)) {
                content.append("刪除了");
                if (StringUtils.isNotBlank(nameValue)) {
                    content.append(nameValue);
                } else if (StringUtils.isNotBlank(idValue)) {
                    content.append(idFieldChinese).append("為").append(idValue).append("的記錄");
                } else {
                    content.append("記錄");
                }
                
            } else {
                content.append(operationType);
                if (StringUtils.isNotBlank(nameValue)) {
                    content.append("了").append(nameValue);
                } else if (StringUtils.isNotBlank(idValue)) {
                    content.append("了").append(idFieldChinese).append("為").append(idValue).append("的記錄");
                }
            }

            return content.toString();
            
        } catch (Exception e) {
            log.warn("自動生成操作內容失敗", e);
            return operationType + "操作";
        }
    }

    /**
     * 提取對象的字段和值
     */
    private static Map<String, Object> extractFieldValues(Object obj) {
        Map<String, Object> fieldValues = new LinkedHashMap<>();
        
        try {
            // 先嘗試轉換為 JSON 對象（更簡單的方式）
            JSONObject jsonObj = JSONObject.parseObject(JSON.toJSONString(obj));
            if (jsonObj != null) {
                for (String key : jsonObj.keySet()) {
                    if (!DEFAULT_EXCLUDE_FIELDS.contains(key)) {
                        Object value = jsonObj.get(key);
                        if (value != null && !isDefaultValue(value)) {
                            fieldValues.put(key, value);
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.debug("使用JSON方式提取字段失敗，嘗試反射方式", e);
            // 如果JSON方式失敗，使用反射
            extractFieldValuesByReflection(obj, fieldValues);
        }
        
        return fieldValues;
    }

    /**
     * 使用反射提取字段值
     */
    private static void extractFieldValuesByReflection(Object obj, Map<String, Object> fieldValues) {
        Class<?> clazz = obj.getClass();
        
        // 跳過 JDK 內部類（如 String、Integer 等），避免模塊系統限制
        if (clazz.getName().startsWith("java.") || clazz.getName().startsWith("javax.")) {
            log.debug("跳過 JDK 內部類: {}", clazz.getName());
            return;
        }
        
        Field[] fields = clazz.getDeclaredFields();
        
        for (Field field : fields) {
            String fieldName = field.getName();
            if (DEFAULT_EXCLUDE_FIELDS.contains(fieldName)) {
                continue;
            }
            
            try {
                // 設置字段可訪問（Java 8 兼容）
                field.setAccessible(true);
                
                Object value = field.get(obj);
                if (value != null && !isDefaultValue(value)) {
                    fieldValues.put(fieldName, value);
                }
            } catch (IllegalAccessException | SecurityException e) {
                log.debug("無法訪問字段: {}", fieldName, e);
            } catch (Exception e) {
                log.debug("提取字段值失敗: {}", fieldName, e);
            }
        }
        
        // 遞歸處理父類字段
        Class<?> superClass = clazz.getSuperclass();
        if (superClass != null && !superClass.equals(Object.class) && 
            !superClass.getName().startsWith("java.")) {
            try {
                extractFieldValuesByReflectionFromClass(obj, superClass, fieldValues);
            } catch (Exception e) {
                log.debug("提取父類字段失敗", e);
            }
        }
    }
    
    /**
     * 從指定類中提取字段值
     */
    private static void extractFieldValuesByReflectionFromClass(Object obj, Class<?> clazz, Map<String, Object> fieldValues) {
        Field[] fields = clazz.getDeclaredFields();
        
        for (Field field : fields) {
            String fieldName = field.getName();
            if (DEFAULT_EXCLUDE_FIELDS.contains(fieldName) || fieldValues.containsKey(fieldName)) {
                continue;
            }
            
            try {
                // 設置字段可訪問（Java 8 兼容）
                field.setAccessible(true);
                
                Object value = field.get(obj);
                if (value != null && !isDefaultValue(value)) {
                    fieldValues.put(fieldName, value);
                }
            } catch (IllegalAccessException | SecurityException e) {
                log.debug("無法訪問字段: {}", fieldName, e);
            } catch (Exception e) {
                log.debug("提取字段值失敗: {}", fieldName, e);
            }
        }
    }

    /**
     * 判斷是否為默認值（空值、0、false等）
     */
    private static boolean isDefaultValue(Object value) {
        if (value == null) {
            return true;
        }
        if (value instanceof String && StringUtils.isBlank((String) value)) {
            return true;
        }
        if (value instanceof Number) {
            Number num = (Number) value;
            if (num instanceof Integer && num.intValue() == 0) {
                return true;
            }
            if (num instanceof Long && num.longValue() == 0L) {
                return true;
            }
            if (num instanceof Double && num.doubleValue() == 0.0) {
                return true;
            }
        }
        if (value instanceof Boolean && !((Boolean) value)) {
            return false; // false 值也保留
        }
        return false;
    }

    /**
     * 獲取字段值作為字符串
     */
    private static String getFieldValueAsString(Map<String, Object> fieldValues, String fieldName) {
        if (StringUtils.isBlank(fieldName) || fieldValues == null) {
            return null;
        }
        
        Object value = fieldValues.get(fieldName);
        if (value == null) {
            return null;
        }
        
        return formatValue(value);
    }

    /**
     * 格式化值
     */
    private static String formatValue(Object value) {
        if (value == null) {
            return null;
        }
        
        if (value instanceof Date) {
            return new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format((Date) value);
        }
        if (value instanceof LocalDate) {
            return value.toString();
        }
        if (value instanceof Boolean) {
            return (Boolean) value ? "是" : "否";
        }
        
        String str = value.toString();
        // 如果字符串過長，截取
        if (str.length() > 50) {
            return str.substring(0, 50) + "...";
        }
        
        return str;
    }

    /**
     * 追加主要字段信息到內容中
     */
    private static void appendMainFields(StringBuilder content, Map<String, Object> fieldValues, 
                                        String idField, String nameField, Object obj) {
        List<String> fieldDescriptions = new ArrayList<>();
        
        // 最多顯示5個主要字段
        int count = 0;
        for (Map.Entry<String, Object> entry : fieldValues.entrySet()) {
            if (count >= 5) {
                break;
            }
            
            String fieldName = entry.getKey();
            // 跳過id和name字段（已經在開頭顯示了）
            if (fieldName.equals(idField) || fieldName.equals(nameField)) {
                continue;
            }
            
            Object value = entry.getValue();
            // 從實體類的@ApiModelProperty注解中讀取字段中文名稱
            String fieldLabel = getFieldLabel(obj, fieldName);
            String valueStr = formatValue(value);
            
            if (StringUtils.isNotBlank(valueStr)) {
                fieldDescriptions.add(fieldLabel + ":" + valueStr);
                count++;
            }
        }
        
        if (!fieldDescriptions.isEmpty()) {
            content.append(",").append(String.join(",", fieldDescriptions));
        }
    }

    /**
     * 獲取字段的中文標籤（從@ApiModelProperty注解中讀取）
     */
    private static String getFieldLabel(Object obj, String fieldName) {
        if (obj == null || fieldName == null) {
            return fieldName;
        }
        
        // 優先從實體類的@ApiModelProperty注解中讀取
        String chineseName = getFieldChineseNameFromAnnotation(obj.getClass(), fieldName);
        if (!chineseName.equals(fieldName)) {
            return chineseName;
        }
        
        // 如果沒有注解，從舊的映射中查找（兼容性）
        String label = FIELD_NAME_MAPPING.get(fieldName);
        if (StringUtils.isNotBlank(label)) {
            return label;
        }
        
        // 如果都沒有，返回字段名本身
        return fieldName;
    }
    
    /**
     * 獲取字段的中文標籤（兼容舊方法）
     */
    private static String getFieldLabel(String fieldName) {
        // 先從映射中查找
        String label = FIELD_NAME_MAPPING.get(fieldName);
        if (StringUtils.isNotBlank(label)) {
            return label;
        }
        return fieldName;
    }

    /**
     * 根據對象自動推斷id和name字段
     */
    public static String[] inferIdAndNameFields(Object obj) {
        if (obj == null) {
            return new String[]{"id", "name"};
        }
        
        Map<String, Object> fieldValues = extractFieldValues(obj);
        
        // 嘗試找到id字段
        String idField = "id";
        if (!fieldValues.containsKey("id")) {
            // 嘗試其他可能的id字段
            for (String field : Arrays.asList("id", "Id", "ID", "primaryKey")) {
                if (fieldValues.containsKey(field)) {
                    idField = field;
                    break;
                }
            }
        }
        
        // 嘗試找到name字段
        String nameField = "name";
        if (!fieldValues.containsKey("name")) {
            // 嘗試其他可能的name字段
            for (String field : Arrays.asList("name", "Name", "title", "Title", 
                    "festivalName", "storeName", "userName", "realName")) {
                if (fieldValues.containsKey(field)) {
                    nameField = field;
                    break;
                }
            }
        }
        
        return new String[]{idField, nameField};
    }
}

