package shop.alien.store.aspect;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.annotation.Order;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.common.TemplateParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.expression.BeanFactoryResolver;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springframework.stereotype.Component;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import shop.alien.entity.store.OperationLog;
import shop.alien.store.service.OperationLogService;
import shop.alien.store.util.ContentGeneratorUtil;
import shop.alien.store.util.DataCompareUtil;
import shop.alien.util.common.JwtUtil;

import javax.servlet.http.HttpServletRequest;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 操作日志切面
 *
 * @author ssk
 * @since 2025-12-09
 */
@Slf4j
@Aspect
@Component
@Order(1)
@RequiredArgsConstructor
public class OperationLogAspect implements ApplicationContextAware {
    
    private ApplicationContext applicationContext;

    private final OperationLogService operationLogService;

    private final SpelExpressionParser spelExpressionParser = new SpelExpressionParser();
    private final DefaultParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
    // 用於解析模板表達式（如 "新增了節假日,節日名稱:#{#holiday.festivalName}"）
    private final TemplateParserContext templateParserContext = new TemplateParserContext("#{", "}");

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    /**
     * 定义切点：所有标注了@OperationLog注解的方法
     */
    @Pointcut("@annotation(shop.alien.store.annotation.ChangeRecordLog)")
    public void operationLogPointcut() {
    }

    /**
     * 环绕通知：记录操作日志
     */
    @Around("operationLogPointcut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        log.info("========== AOP 切面被觸發 ==========");
        log.info("目標類: {}", joinPoint.getTarget().getClass().getName());
        log.info("方法: {}", joinPoint.getSignature().getName());
        
        // 在方法执行前获取注解信息，用于查询修改前的数据
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        shop.alien.store.annotation.ChangeRecordLog annotation = method.getAnnotation(shop.alien.store.annotation.ChangeRecordLog.class);
        
        // 在方法执行前查询修改前的数据（对于UPDATE操作，必须在方法执行前查询）
        Object beforeDataObj = null;
        if (annotation != null && annotation.recordBefore() && annotation.type().name().equals("UPDATE")) {
            try {
                log.info("========== 方法執行前：開始查詢修改前的數據 ==========");
                Object[] args = joinPoint.getArgs();
                String[] parameterNames = parameterNameDiscoverer.getParameterNames(method);
                
                Object paramObj = null;
                Object idValue = null;
                
                // 優先使用注解中指定的ID參數名
                if (annotation != null && StringUtils.isNotBlank(annotation.idParam()) && args != null && parameterNames != null) {
                    for (int i = 0; i < parameterNames.length; i++) {
                        if (annotation.idParam().equals(parameterNames[i]) && args[i] != null) {
                            idValue = args[i];
                            log.info("從注解指定的參數名中獲取ID: 參數名={}, ID值={}, 類型: {}", 
                                    annotation.idParam(), idValue, args[i].getClass().getSimpleName());
                            break;
                        }
                    }
                }
                
                // 如果沒有通過指定參數名找到ID，則使用原來的邏輯
                if (idValue == null && args != null && parameterNames != null) {
                    for (int i = 0; i < args.length; i++) {
                        Object arg = args[i];
                        if (arg != null) {
                            // 如果參數本身就是ID（Integer、Long、String等基本類型）
                            if (isPrimitiveOrWrapper(arg.getClass()) || isString(arg.getClass())) {
                                // 如果指定了mapper，可以直接使用這個參數作為ID
                                if (annotation != null && annotation.mapper() != null && annotation.mapper() != BaseMapper.class) {
                                    // 如果沒有指定idParam，或者參數名是"id"，則使用
                                    if (StringUtils.isBlank(annotation.idParam()) || "id".equals(parameterNames[i])) {
                                        idValue = arg;
                                        log.info("參數本身就是ID: {}, 參數名: {}, 類型: {}", 
                                                idValue, parameterNames[i], arg.getClass().getSimpleName());
                                        break;
                                    }
                                }
                            } else {
                                // 嘗試從對象中提取ID
                                idValue = extractIdFromObject(arg, annotation.idField());
                                if (idValue != null) {
                                    paramObj = arg;
                                    log.info("從參數中提取到ID: {}, 對象類型: {}", idValue, arg.getClass().getSimpleName());
                                    break;
                                }
                            }
                        }
                    }
                }
                
                // 如果找到了ID，通過Mapper查詢原始數據（方法執行前）
                // 如果注解中指定了mapper，可以直接使用mapper查詢，不需要paramObj
                if (idValue != null) {
                    Class<?> entityClass = paramObj != null ? paramObj.getClass() : null;
                    // 如果指定了mapper，實體類會從mapper中提取，所以entityClass可以為null
                    if (annotation != null && annotation.mapper() != null && annotation.mapper() != BaseMapper.class) {
                        entityClass = null; // 實體類將從mapper中提取
                    }
                    beforeDataObj = queryBeforeDataById(entityClass, idValue, annotation);
                    if (beforeDataObj != null) {
                        log.info("✓ 成功查詢到修改前的數據，類型: {}", beforeDataObj.getClass().getSimpleName());
                        log.info("修改前的數據JSON: {}", JSON.toJSONString(beforeDataObj));
                    } else {
                        log.warn("查詢修改前的數據返回null，ID: {}", idValue);
                    }
                } else {
                    log.warn("無法從參數中提取ID，跳過查詢修改前的數據");
                }
            } catch (Exception e) {
                log.error("方法執行前查詢修改前的數據失敗", e);
            }
        }
        
        long startTime = System.currentTimeMillis();
        Object result = null;
        Exception exception = null;
        
        try {
            // 执行目标方法
            result = joinPoint.proceed();
            log.info("目標方法執行成功，返回值: {}", result != null ? result.getClass().getSimpleName() : "null");
            return result;
        } catch (Exception e) {
            exception = e;
            log.error("目標方法執行失敗", e);
            throw e;
        } finally {
            try {
                // 记录操作日志（传入方法执行前查询的修改前数据）
                log.info("開始記錄操作日誌...");
                recordOperationLog(joinPoint, result, exception, startTime, beforeDataObj);
            } catch (Exception e) {
                log.error("记录操作日志失败", e);
                e.printStackTrace();
            }
        }
    }

    /**
     * 记录操作日志
     */
    private void recordOperationLog(ProceedingJoinPoint joinPoint, Object result, Exception exception, long startTime, Object preQueryBeforeData) {
        try {
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            Method method = signature.getMethod();
            shop.alien.store.annotation.ChangeRecordLog operationLogAnnotation = method.getAnnotation(shop.alien.store.annotation.ChangeRecordLog.class);

            if (operationLogAnnotation == null) {
                log.warn("方法 {} 上未找到 @ChangeRecordLog 註解", method.getName());
                return;
            }

            log.info("開始記錄操作日誌: 方法={}, 模組={}", method.getName(), operationLogAnnotation.module());

            // 获取方法参数
            Object[] args = joinPoint.getArgs();
            String[] parameterNames = parameterNameDiscoverer.getParameterNames(method);
            
            // 创建SpEL上下文
            EvaluationContext context = createEvaluationContext(method, args, parameterNames, result);

            // 构建操作日志对象
            OperationLog operationLog = new OperationLog();
            
            // 设置用户信息
            setUserInfo(operationLog);

            // 设置操作模块
            operationLog.setOperationModule(parseSpEL(operationLogAnnotation.module(), context, String.class));

            // 设置操作类型
            operationLog.setOperationType(operationLogAnnotation.type().getDescription());

            // 设置操作内容（支持SpEL表达式，但優先使用自動生成）
            String content = null;
            
            // 如果content不為空，嘗試解析SpEL表達式
            if (StringUtils.isNotBlank(operationLogAnnotation.content())) {
                content = parseSpEL(operationLogAnnotation.content(), context, String.class);
            }
            
            // 如果content為空或為空字符串，嘗試自動生成
            if (StringUtils.isBlank(content)) {
                content = autoGenerateContent(operationLogAnnotation, joinPoint, args, result);
            }
            
            operationLog.setOperationContent(content);

            // 设置请求信息
            setRequestInfo(operationLog, joinPoint);

            // 设置操作时间
            operationLog.setOperationTime(new Date());

            // 记录修改前后的数据（传入方法执行前查询的修改前数据）
            if (operationLogAnnotation.recordBefore() || operationLogAnnotation.recordAfter()) {
                recordDataChange(operationLog, joinPoint, operationLogAnnotation, context, result, preQueryBeforeData);
            }

            // 保存操作日志
            operationLogService.saveOperationLog(operationLog);
            log.info("操作日誌記錄完成: 模組={}, 類型={}, 內容={}", 
                    operationLog.getOperationModule(), 
                    operationLog.getOperationType(),
                    operationLog.getOperationContent());
        } catch (Exception e) {
            log.error("記錄操作日誌時發生異常", e);
            e.printStackTrace();
        }
    }

    /**
     * 创建SpEL表达式上下文
     */
    private EvaluationContext createEvaluationContext(Method method, Object[] args, String[] parameterNames, Object result) {
        StandardEvaluationContext context = new StandardEvaluationContext();
        
        // 添加方法参数
        if (parameterNames != null && args != null) {
            for (int i = 0; i < parameterNames.length; i++) {
                context.setVariable(parameterNames[i], args[i]);
            }
        }
        
        // 添加返回值
        if (result != null) {
            context.setVariable("result", result);
        }

        // 添加方法信息
        context.setVariable("method", method);
        
        // 添加 Spring Bean 解析器，支持在 SpEL 中訪問 Spring Bean
        // 例如：@holidayService.getHolidayById(#id) 或 @holidayServiceImpl.getHolidayById(#id)
        if (applicationContext != null) {
            try {
                context.setBeanResolver(new BeanFactoryResolver(applicationContext));
                log.debug("BeanResolver設置成功");
            } catch (Exception e) {
                log.error("設置BeanResolver失敗", e);
            }
        } else {
            log.warn("ApplicationContext為null，無法設置BeanResolver");
        }
        
        return context;
    }

    /**
     * 解析SpEL表达式
     * 支持兩種模式：
     * 1. 純字符串：直接返回
     * 2. 包含SpEL表達式的模板字符串（如 "新增了節假日,節日名稱:#{#holiday.festivalName}"）：解析表達式並替換
     * 3. 純SpEL表達式（如 "#{#holiday.festivalName}"）：解析並返回結果
     */
    private <T> T parseSpEL(String expression, EvaluationContext context, Class<T> clazz) {
        if (expression == null || expression.trim().isEmpty()) {
            return null;
        }
        
        // 如果字符串不包含SpEL表達式語法（#{}），直接返回字符串
        if (!expression.contains("#{") && !expression.contains("${")) {
            if (clazz == String.class) {
                return clazz.cast(expression);
            }
            // 如果不是String類型，嘗試轉換
            try {
                if (clazz.isInstance(expression)) {
                    return clazz.cast(expression);
                }
            } catch (Exception e) {
                log.debug("類型轉換失敗: {}", expression, e);
            }
            return null;
        }
        
        try {
            // 如果字符串包含模板表達式（如 "新增了節假日,節日名稱:#{#holiday.festivalName}"）
            // 使用 TemplateParserContext 來解析模板
            if (expression.contains("#{") && clazz == String.class) {
                Expression exp = spelExpressionParser.parseExpression(expression, templateParserContext);
                Object value = exp.getValue(context, String.class);
                if (value != null) {
                    return clazz.cast(value);
                }
            }
            
            // 如果是純SpEL表達式（如 "#{#holiday.festivalName}" 或 "@holidayService.getHolidayById(#id)"），直接解析
            Expression exp = spelExpressionParser.parseExpression(expression);
            Object value = exp.getValue(context);
            if (value == null) {
                log.debug("SpEL表達式解析結果為null: {}", expression);
                return null;
            }
            
            // 檢查解析結果是否為字符串且等於原始表達式（表示解析失敗）
            if (value instanceof String) {
                String valueStr = (String) value;
                // 如果返回的字符串等於原始表達式，或者包含 @ 或 # 符號，可能是解析失敗
                if (valueStr.equals(expression) || 
                    (expression.startsWith("@") && valueStr.startsWith("@")) ||
                    (expression.startsWith("#") && valueStr.startsWith("#"))) {
                    log.error("SpEL表達式解析失敗，返回了原始表達式字符串。表達式: {}, 返回值: {}", expression, valueStr);
                    // 對於非String類型，返回null而不是原始字符串，避免後續處理錯誤
                    if (clazz != String.class) {
                        return null;
                    }
                }
            }
            
            if (clazz.isInstance(value)) {
                return clazz.cast(value);
            }
            return (T) value;
        } catch (Exception e) {
            log.error("解析SpEL表达式失败: {}, 錯誤: {}", expression, e.getMessage(), e);
            // 如果解析失敗，且是String類型，返回原字符串
            // 對於Object類型，返回null而不是原始字符串，避免後續JSON解析錯誤
            if (clazz == String.class) {
                return clazz.cast(expression);
            }
            // 對於Object.class，返回null
            if (clazz == Object.class) {
                return null;
            }
            return null;
        }
    }

    /**
     * 设置用户信息
     */
    private void setUserInfo(OperationLog operationLog) {
        try {
            JSONObject userInfo = JwtUtil.getCurrentUserInfo();
            if (userInfo != null) {
                operationLog.setAccountId(userInfo.getString("userId"));
                operationLog.setAccount(userInfo.getString("phone") != null ? userInfo.getString("phone") : userInfo.getString("account"));
                operationLog.setName(userInfo.getString("userName") != null ? userInfo.getString("userName") : userInfo.getString("name"));
                operationLog.setPosition(userInfo.getString("position"));
                operationLog.setDepartment(userInfo.getString("department"));
                
                // 设置用户类型
                String userType = userInfo.getString("userType");
                if ("platform".equals(userType) || "platform".equals(userInfo.getString("role"))) {
                    operationLog.setUserType("平台");
                } else if ("store".equals(userType) || "merchant".equals(userType)) {
                    operationLog.setUserType("商家");
                } else if ("lawyer".equals(userType)) {
                    operationLog.setUserType("律师");
                } else {
                    operationLog.setUserType("用户");
                }
            }
        } catch (Exception e) {
            log.warn("获取用户信息失败", e);
        }
    }

    /**
     * 设置请求信息
     */
    private void setRequestInfo(OperationLog operationLog, ProceedingJoinPoint joinPoint) {
        try {
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            if (attributes != null) {
                HttpServletRequest request = attributes.getRequest();
                operationLog.setMethod(request.getMethod());
                operationLog.setRequestPath(request.getRequestURI());
                operationLog.setIpAddress(getIpAddress(request));
                
                // 获取请求参数
                Map<String, Object> params = new HashMap<>();
                if (request.getParameterMap() != null && !request.getParameterMap().isEmpty()) {
                    request.getParameterMap().forEach((key, values) -> {
                        if (values != null && values.length > 0) {
                            params.put(key, values.length == 1 ? values[0] : values);
                        }
                    });
                }
                operationLog.setRequestParams(JSON.toJSONString(params));
            }

            // 设置方法信息
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            operationLog.setMethod(signature.getDeclaringTypeName() + "." + signature.getMethod().getName());
        } catch (Exception e) {
            log.warn("获取请求信息失败", e);
        }
    }

    /**
     * 记录数据变更（修改前后的数据）
     */
    private void recordDataChange(OperationLog operationLog, ProceedingJoinPoint joinPoint, 
                                  shop.alien.store.annotation.ChangeRecordLog annotation,
                                  EvaluationContext context, Object result, Object preQueryBeforeData) {
        try {
            // 使用在方法执行前查询的修改前数据（如果存在）
            Object beforeDataObj = preQueryBeforeData;
            Object afterDataObj = null;  // 修改後的數據對象
            
            // 對於UPDATE操作，先從方法參數中獲取修改後的數據
            if (annotation.type().name().equals("UPDATE")) {
                Object[] args = joinPoint.getArgs();
                if (args != null) {
                    for (Object arg : args) {
                        if (arg != null && !isPrimitiveOrWrapper(arg.getClass()) && !isString(arg.getClass())) {
                            // 找到第一個非基本類型的參數對象（通常是實體對象）
                            afterDataObj = arg;
                            log.info("從方法參數中獲取修改後的數據，類型: {}", afterDataObj.getClass().getSimpleName());
                            break;
                        }
                    }
                }
            }
            
            // 如果方法执行前没有查询到修改前的数据，则在这里查询（对于非UPDATE操作或其他情况）
            if (annotation.recordBefore() && beforeDataObj == null) {
                try {
                    log.info("========== 方法執行後：開始查詢修改前的數據 ==========");
                    // 從方法參數中提取ID和對象
                    Object[] args = joinPoint.getArgs();
                    String[] parameterNames = parameterNameDiscoverer.getParameterNames(
                            ((MethodSignature) joinPoint.getSignature()).getMethod());
                    
                    Object paramObj = null;
                    Object idValue = null;
                    
                    // 優先使用注解中指定的ID參數名
                    if (annotation != null && StringUtils.isNotBlank(annotation.idParam()) && args != null && parameterNames != null) {
                        for (int i = 0; i < parameterNames.length; i++) {
                            if (annotation.idParam().equals(parameterNames[i]) && args[i] != null) {
                                idValue = args[i];
                                log.info("從注解指定的參數名中獲取ID: 參數名={}, ID值={}, 類型: {}", 
                                        annotation.idParam(), idValue, args[i].getClass().getSimpleName());
                                break;
                            }
                        }
                    }
                    
                    // 如果沒有通過指定參數名找到ID，則使用原來的邏輯
                    if (idValue == null && args != null && parameterNames != null) {
                        for (int i = 0; i < args.length; i++) {
                            Object arg = args[i];
                            if (arg != null) {
                                // 如果參數本身就是ID（Integer、Long、String等基本類型）
                                if (isPrimitiveOrWrapper(arg.getClass()) || isString(arg.getClass())) {
                                    // 如果指定了mapper，可以直接使用這個參數作為ID
                                    if (annotation != null && annotation.mapper() != null && annotation.mapper() != BaseMapper.class) {
                                        // 如果沒有指定idParam，或者參數名是"id"，則使用
                                        if (StringUtils.isBlank(annotation.idParam()) || "id".equals(parameterNames[i])) {
                                            idValue = arg;
                                            log.info("參數本身就是ID: {}, 參數名: {}, 類型: {}", 
                                                    idValue, parameterNames[i], arg.getClass().getSimpleName());
                                            break;
                                        }
                                    } else {
                                        // 沒有指定mapper，需要找到對應的實體類
                                        idValue = arg;
                                        log.info("參數本身就是ID: {}", idValue);
                                        // 嘗試從其他參數中找實體對象
                                        for (int j = 0; j < args.length; j++) {
                                            if (j != i && args[j] != null && 
                                                !isPrimitiveOrWrapper(args[j].getClass()) && 
                                                !isString(args[j].getClass())) {
                                                paramObj = args[j];
                                                break;
                                            }
                                        }
                                        break;
                                    }
                                } else {
                                    // 嘗試從對象中提取ID
                                    idValue = extractIdFromObject(arg, annotation.idField());
                                    if (idValue != null) {
                                        paramObj = arg;
                                        log.info("從參數中提取到ID: {}, 對象類型: {}", idValue, arg.getClass().getSimpleName());
                                        break;
                                    }
                                }
                            }
                        }
                    }
                    
                    // 如果找到了ID，通過Mapper查詢原始數據
                    // 如果注解中指定了mapper，可以直接使用mapper查詢，不需要paramObj
                    if (idValue != null) {
                        Class<?> entityClass = paramObj != null ? paramObj.getClass() : null;
                        // 如果指定了mapper，實體類會從mapper中提取，所以entityClass可以為null
                        if (annotation != null && annotation.mapper() != null && annotation.mapper() != BaseMapper.class) {
                            entityClass = null; // 實體類將從mapper中提取
                        }
                        beforeDataObj = queryBeforeDataById(entityClass, idValue, annotation);
                    } else {
                        log.warn("無法從參數中提取ID，跳過查詢修改前的數據");
                    }
                } catch (Exception e) {
                    log.error("查詢修改前的數據失敗", e);
                    // 記錄錯誤但不影響主流程
                }
            }
            
            // 记录修改前的数据
            if (beforeDataObj != null) {
                try {
                    String beforeData = JSON.toJSONString(beforeDataObj);
                    operationLog.setBeforeData(beforeData);
                    log.info("========== 成功獲取修改前的數據 ==========");
                    log.info("修改前的數據類型: {}", beforeDataObj.getClass().getName());
                    log.info("修改前的完整JSON: {}", beforeData);
                    log.info("數據長度: {}", beforeData.length());
                } catch (Exception e) {
                    log.error("序列化修改前的數據失敗", e);
                    operationLog.setBeforeData("序列化失敗: " + e.getMessage());
                }
            } else if (annotation.recordBefore()) {
                log.error("========== 修改前的數據為null ==========");
            }

            // 记录修改后的数据
            if (annotation.recordAfter()) {
                // 優先使用從參數中獲取的修改後數據（對於UPDATE操作）
                Object actualResult = afterDataObj;
                
                // 如果參數中沒有，則從返回值中提取
                if (actualResult == null && result != null) {
                    log.info("========== 從返回值提取修改後的數據 ==========");
                    log.info("result類型: {}", result.getClass().getName());
                    log.info("result的JSON: {}", JSON.toJSONString(result));
                    
                    actualResult = extractDataFromResult(result);
                    
                    log.info("提取後的actualResult類型: {}", actualResult != null ? actualResult.getClass().getName() : "null");
                    log.info("提取後的actualResult的JSON: {}", actualResult != null ? JSON.toJSONString(actualResult) : "null");
                }
                
                if (actualResult != null) {
                    String afterData = JSON.toJSONString(actualResult);
                    operationLog.setAfterData(afterData);
                    log.info("記錄修改後的數據，類型: {}, 數據長度: {}", 
                            actualResult.getClass().getSimpleName(), 
                            afterData.length());
                } else {
                    log.warn("無法獲取修改後的數據");
                }
                
                // 如果同時有修改前的數據，則生成詳細的變更描述
                if (beforeDataObj != null && annotation.recordBefore() && actualResult != null) {
                    try {
                        // 使用修改後的數據對象
                        Object afterObj = actualResult;
                        
                        if (afterObj == null) {
                            log.warn("修改後的對象為null，無法進行比較");
                        } else {
                            log.info("開始生成詳細變更描述，修改前對象類型: {}, 修改後對象類型: {}", 
                                    beforeDataObj.getClass().getSimpleName(), 
                                    afterObj.getClass().getSimpleName());
                            
                            // 輸出實際的JSON數據以便調試
                            String beforeJson = JSON.toJSONString(beforeDataObj);
                            String afterJson = JSON.toJSONString(afterObj);
                            log.info("========== 數據比較開始 ==========");
                            log.info("修改前的完整JSON: {}", beforeJson);
                            log.info("修改後的完整JSON: {}", afterJson);
                            log.info("修改前的對象類型: {}", beforeDataObj.getClass().getName());
                            log.info("修改後的對象類型: {}", afterObj.getClass().getName());
                            
                            // 自動推斷id和name字段
                            String[] idAndName = ContentGeneratorUtil.inferIdAndNameFields(beforeDataObj);
                            String idField = idAndName[0];
                            String nameField = idAndName[1];
                            
                            log.info("推斷的字段: idField={}, nameField={}", idField, nameField);
                            
                            // 生成詳細的變更描述
                            String changeDesc = DataCompareUtil.generateChangeDescription(beforeDataObj, afterObj, idField, nameField);
                            if (changeDesc != null && !changeDesc.isEmpty()) {
                                log.info("生成的變更描述: {}", changeDesc);
                                // 如果操作內容為空或使用默認值，則使用變更描述
                                String currentContent = operationLog.getOperationContent();
                                if (currentContent == null || currentContent.isEmpty() || 
                                    (annotation.content() != null && !annotation.content().isEmpty() && currentContent.equals(annotation.content()))) {
                                    operationLog.setOperationContent(changeDesc);
                                } else {
                                    // 否則追加變更描述
                                    operationLog.setOperationContent(currentContent + " - " + changeDesc);
                                }
                            } else {
                                log.warn("變更描述為空，可能沒有字段變更或比較失敗");
                            }
                        }
                    } catch (Exception e) {
                        log.error("生成變更描述失敗", e);
                        e.printStackTrace();
                    }
                }
            }
        } catch (Exception e) {
            log.warn("记录数据变更失败", e);
        }
    }

    /**
     * 自動生成操作內容
     * 當content為空時，根據操作類型和對象字段自動生成
     */
    private String autoGenerateContent(shop.alien.store.annotation.ChangeRecordLog annotation,
                                      ProceedingJoinPoint joinPoint, Object[] args, Object result) {
        try {
            String operationType = annotation.type().getDescription();
            
            // 嘗試從方法參數或返回值中獲取對象
            Object targetObj = null;
            
            // 優先使用返回值（對於新增、修改操作）
            if (result != null && ("新增".equals(operationType) || "修改".equals(operationType) || "更新".equals(operationType))) {
                // 如果返回值是 R 包裝類，嘗試獲取 data
                if (result.getClass().getName().contains("R")) {
                    try {
                        java.lang.reflect.Method getDataMethod = result.getClass().getMethod("getData");
                        Object data = getDataMethod.invoke(result);
                        if (data != null) {
                            targetObj = data;
                        }
                    } catch (Exception e) {
                        // 如果獲取失敗，使用原返回值
                        targetObj = result;
                    }
                } else {
                    targetObj = result;
                }
            }
            // 如果沒有返回值，嘗試從參數中獲取第一個對象參數
            else if (args != null && args.length > 0) {
                for (Object arg : args) {
                    if (arg != null && !isPrimitiveOrWrapper(arg.getClass()) && !isString(arg.getClass())) {
                        targetObj = arg;
                        break;
                    }
                }
            }
            
            if (targetObj != null) {
                // 自動推斷id和name字段
                String[] idAndName = ContentGeneratorUtil.inferIdAndNameFields(targetObj);
                String idField = idAndName[0];
                String nameField = idAndName[1];
                
                // 生成內容
                return ContentGeneratorUtil.generateContent(operationType, targetObj, idField, nameField);
            }
            
            // 如果無法獲取對象，返回默認內容
            return operationType + "操作";
            
        } catch (Exception e) {
            log.warn("自動生成操作內容失敗", e);
            return annotation.type().getDescription() + "操作";
        }
    }

    /**
     * 判斷是否為基本類型或包裝類型
     */
    private boolean isPrimitiveOrWrapper(Class<?> clazz) {
        return clazz.isPrimitive() ||
               clazz == Boolean.class ||
               clazz == Byte.class ||
               clazz == Character.class ||
               clazz == Short.class ||
               clazz == Integer.class ||
               clazz == Long.class ||
               clazz == Float.class ||
               clazz == Double.class;
    }

    /**
     * 判斷是否為字符串類型
     */
    private boolean isString(Class<?> clazz) {
        return clazz == String.class;
    }

    /**
     * 获取客户端IP地址
     */
    private String getIpAddress(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

    /**
     * 從對象中提取ID值
     */
    private Object extractIdFromObject(Object obj, String idFieldName) {
        if (obj == null) {
            return null;
        }
        
        try {
            // 先嘗試通過JSON方式獲取
            JSONObject jsonObj = JSONObject.parseObject(JSON.toJSONString(obj));
            Object id = jsonObj.get(idFieldName);
            if (id != null) {
                return id;
            }
            
            // 如果JSON方式失敗，嘗試反射
            Class<?> clazz = obj.getClass();
            Field field = clazz.getDeclaredField(idFieldName);
            field.setAccessible(true);
            return field.get(obj);
        } catch (Exception e) {
            log.debug("提取ID失敗，字段名: {}, 對象類型: {}", idFieldName, obj.getClass().getSimpleName(), e);
            return null;
        }
    }

    /**
     * 通過ID查詢修改前的數據
     */
    private Object queryBeforeDataById(Class<?> entityClass, Object id, shop.alien.store.annotation.ChangeRecordLog annotation) {
        if (id == null) {
            return null;
        }
        
        try {
            BaseMapper<?> mapper = null;
            Class<?> actualEntityClass = entityClass;
            
            // 優先使用注解中指定的Mapper
            if (annotation != null && annotation.mapper() != null && annotation.mapper() != BaseMapper.class) {
                try {
                    if (applicationContext != null) {
                        // 從Spring容器中獲取指定類型的Mapper實例
                        mapper = applicationContext.getBean(annotation.mapper());
                        log.info("使用注解中指定的Mapper: {}", annotation.mapper().getSimpleName());
                        
                        // 從Mapper的泛型參數中提取實體類
                        actualEntityClass = extractEntityClassFromMapper(annotation.mapper());
                        if (actualEntityClass != null) {
                            log.info("從Mapper泛型中提取到實體類: {}", actualEntityClass.getSimpleName());
                        } else {
                            log.warn("無法從Mapper泛型中提取實體類，使用參數中的實體類");
                            actualEntityClass = entityClass;
                        }
                    }
                } catch (Exception e) {
                    log.warn("無法從容器中獲取注解指定的Mapper: {}", annotation.mapper().getSimpleName(), e);
                }
            }
            
            // 如果注解中沒有指定Mapper或獲取失敗，則從容器中查找
            if (mapper == null && applicationContext != null) {
                if (entityClass == null) {
                    log.warn("未指定Mapper且無法從參數中獲取實體類，無法查詢數據");
                    return null;
                }
                
                // 根據實體類名推斷Mapper名稱
                // 例如：EssentialHolidayComparison -> EssentialHolidayComparisonMapper
                String entityName = entityClass.getSimpleName();
                String mapperBeanName = entityName.substring(0, 1).toLowerCase() + entityName.substring(1) + "Mapper";
                
                try {
                    // 先嘗試標準命名
                    mapper = (BaseMapper<?>) applicationContext.getBean(mapperBeanName);
                    if (mapper != null) {
                        log.info("通過標準命名找到Mapper: {}", mapperBeanName);
                    }
                } catch (Exception e) {
                    log.debug("無法獲取Mapper: {}", mapperBeanName, e);
                }
                
                // 如果標準命名失敗，嘗試查找所有BaseMapper類型的Bean
                if (mapper == null) {
                    try {
                        String[] beanNames = applicationContext.getBeanNamesForType(BaseMapper.class);
                        for (String beanName : beanNames) {
                            try {
                                BaseMapper<?> candidateMapper = applicationContext.getBean(beanName, BaseMapper.class);
                                // 檢查Mapper的泛型類型是否匹配
                                java.lang.reflect.Type[] types = candidateMapper.getClass().getGenericInterfaces();
                                for (java.lang.reflect.Type type : types) {
                                    if (type instanceof java.lang.reflect.ParameterizedType) {
                                        java.lang.reflect.ParameterizedType pt = (java.lang.reflect.ParameterizedType) type;
                                        if (pt.getRawType().equals(BaseMapper.class)) {
                                            java.lang.reflect.Type[] actualTypes = pt.getActualTypeArguments();
                                            if (actualTypes.length > 0 && actualTypes[0] instanceof Class) {
                                                Class<?> mapperEntityClass = (Class<?>) actualTypes[0];
                                                if (mapperEntityClass.equals(entityClass)) {
                                                    mapper = candidateMapper;
                                                    log.info("通過泛型匹配找到Mapper: {}", beanName);
                                                    break;
                                                }
                                            }
                                        }
                                    }
                                }
                                if (mapper != null) {
                                    break;
                                }
                            } catch (Exception e) {
                                // 繼續查找下一個
                            }
                        }
                    } catch (Exception e) {
                        log.debug("查找Mapper失敗", e);
                    }
                }
            }
            
            // 使用找到的Mapper查詢數據
            if (mapper != null) {
                Serializable serializableId = convertToSerializable(id);
                if (serializableId != null) {
                    Object result = mapper.selectById(serializableId);
                    log.info("通過Mapper查詢成功，Mapper: {}, 實體類: {}, ID: {}", 
                            mapper.getClass().getSimpleName(), 
                            actualEntityClass != null ? actualEntityClass.getSimpleName() : "未知", 
                            id);
                    return result;
                }
            }
            
            log.warn("無法找到對應的Mapper，實體類: {}, ID: {}", 
                    actualEntityClass != null ? actualEntityClass.getSimpleName() : "未知", id);
            return null;
        } catch (Exception e) {
            log.error("查詢修改前的數據失敗，實體類: {}, ID: {}", 
                    entityClass != null ? entityClass.getSimpleName() : "未知", id, e);
            return null;
        }
    }
    
    /**
     * 從Mapper類的泛型參數中提取實體類
     */
    private Class<?> extractEntityClassFromMapper(Class<? extends BaseMapper> mapperClass) {
        if (mapperClass == null || mapperClass == BaseMapper.class) {
            return null;
        }
        
        try {
            // 獲取Mapper接口的泛型參數
            java.lang.reflect.Type[] types = mapperClass.getGenericInterfaces();
            for (java.lang.reflect.Type type : types) {
                if (type instanceof java.lang.reflect.ParameterizedType) {
                    java.lang.reflect.ParameterizedType pt = (java.lang.reflect.ParameterizedType) type;
                    if (pt.getRawType().equals(BaseMapper.class)) {
                        java.lang.reflect.Type[] actualTypes = pt.getActualTypeArguments();
                        if (actualTypes.length > 0 && actualTypes[0] instanceof Class) {
                            return (Class<?>) actualTypes[0];
                        }
                    }
                }
            }
            
            // 如果直接繼承的接口沒有泛型，嘗試從父類獲取
            java.lang.reflect.Type superclass = mapperClass.getGenericSuperclass();
            if (superclass instanceof java.lang.reflect.ParameterizedType) {
                java.lang.reflect.ParameterizedType pt = (java.lang.reflect.ParameterizedType) superclass;
                if (pt.getRawType().equals(BaseMapper.class)) {
                    java.lang.reflect.Type[] actualTypes = pt.getActualTypeArguments();
                    if (actualTypes.length > 0 && actualTypes[0] instanceof Class) {
                        return (Class<?>) actualTypes[0];
                    }
                }
            }
        } catch (Exception e) {
            log.warn("從Mapper類中提取實體類失敗: {}", mapperClass.getSimpleName(), e);
        }
        
        return null;
    }

    /**
     * 從結果對象中提取實際數據（處理R包裝類）
     */
    private Object extractDataFromResult(Object result) {
        if (result == null) {
            return null;
        }
        
        String resultClassName = result.getClass().getName();
        log.debug("提取數據，result類型: {}", resultClassName);
        
        // 如果不是R包裝類，直接返回
        if (!resultClassName.contains("R")) {
            return result;
        }
        
        // 嘗試多種方法獲取data
        try {
            // 方法1: 嘗試 getData() 方法
            try {
                java.lang.reflect.Method getDataMethod = result.getClass().getMethod("getData");
                Object data = getDataMethod.invoke(result);
                if (data != null) {
                    log.info("通過getData()方法從R對象中提取data成功，類型: {}", data.getClass().getSimpleName());
                    return data;
                }
            } catch (Exception e) {
                log.debug("getData()方法不存在", e);
            }
            
            // 方法2: 嘗試 data() 方法
            try {
                java.lang.reflect.Method dataMethod = result.getClass().getMethod("data");
                Object data = dataMethod.invoke(result);
                if (data != null) {
                    log.info("通過data()方法從R對象中提取data成功，類型: {}", data.getClass().getSimpleName());
                    return data;
                }
            } catch (Exception e) {
                log.debug("data()方法不存在", e);
            }
            
            // 方法3: 嘗試通過字段獲取
            try {
                java.lang.reflect.Field dataField = result.getClass().getDeclaredField("data");
                dataField.setAccessible(true);
                Object data = dataField.get(result);
                if (data != null) {
                    log.info("通過字段從R對象中提取data成功，類型: {}", data.getClass().getSimpleName());
                    return data;
                }
            } catch (Exception e) {
                log.debug("無法通過字段獲取data", e);
            }
            
            log.warn("無法從R對象中提取data，返回原對象。R對象: {}", JSON.toJSONString(result));
            return result;
        } catch (Exception e) {
            log.error("提取R對象中的data失敗", e);
            return result;
        }
    }

    /**
     * 將對象轉換為 Serializable 類型
     */
    private Serializable convertToSerializable(Object id) {
        if (id == null) {
            return null;
        }
        
        // 如果已經是 Serializable 類型，直接返回
        if (id instanceof Serializable) {
            return (Serializable) id;
        }
        
        // 處理常見的 ID 類型
        if (id instanceof Integer) {
            return (Integer) id;
        } else if (id instanceof Long) {
            return (Long) id;
        } else if (id instanceof String) {
            return (String) id;
        } else if (id instanceof Number) {
            // 其他數字類型轉換為 Long
            return ((Number) id).longValue();
        }
        
        // 嘗試轉換為字符串
        try {
            return id.toString();
        } catch (Exception e) {
            log.warn("無法將ID轉換為Serializable: {}", id, e);
            return null;
        }
    }
}

