package shop.alien.store.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;
import shop.alien.entity.store.*;
import shop.alien.entity.store.vo.StoreOperationalStatisticsComparisonVo;
import shop.alien.entity.store.vo.StoreOperationalStatisticsVo;
import shop.alien.mapper.*;
import shop.alien.store.service.StoreOperationalStatisticsService;
import shop.alien.store.util.LifeDynamicsIdentityHelper;
import shop.alien.store.util.StatisticsComparisonImageUtil;
import shop.alien.store.util.ai.AiAuthTokenUtil;
import shop.alien.store.util.ai.AiAuthTokenUtil;
import shop.alien.util.ali.AliOSSUtil;
import shop.alien.util.common.RandomCreateUtil;
import shop.alien.util.pdf.ImageToPdfUtil;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 商家经营数据统计服务实现类
 *
 * @author system
 * @version 1.0
 * @date 2026/01/05
 */
@Slf4j
@Service
@RequiredArgsConstructor
@RefreshScope
public class StoreOperationalStatisticsServiceImpl implements StoreOperationalStatisticsService {

    private final LifeBrowseRecordMapper lifeBrowseRecordMapper;
    private final LifeCollectMapper lifeCollectMapper;
    private final StoreClockInMapper storeClockInMapper;
    private final LifeUserDynamicsMapper lifeUserDynamicsMapper;

    private final LifeDynamicsIdentityHelper dynamicsIdentityHelper;
    private final StoreCommentMapper storeCommentMapper;
    private final LifeCommentMapper lifeCommentMapper;
    private final LifeLikeRecordMapper lifeLikeRecordMapper;
    private final LifeFansMapper lifeFansMapper;
    private final LifeBlacklistMapper lifeBlacklistMapper;
    private final LifeDiscountCouponStoreFriendMapper lifeDiscountCouponStoreFriendMapper;
    private final LifeDiscountCouponUserMapper lifeDiscountCouponUserMapper;
    private final LifeCouponMapper lifeCouponMapper;
    private final CommonRatingMapper commonRatingMapper;
    private final StoreEvaluationMapper storeEvaluationMapper;
    private final StoreCommentAppealMapper storeCommentAppealMapper;
    private final StorePriceMapper storePriceMapper;
    private final StoreCuisineMapper storeCuisineMapper;
    private final StoreInfoMapper storeInfoMapper;
    private final StoreUserMapper storeUserMapper;
    private final StoreOperationalStatisticsHistoryMapper statisticsHistoryMapper;
    private final StoreTrackStatisticsMapper storeTrackStatisticsMapper;
    private final AliOSSUtil aliOSSUtil;
    private final AiAuthTokenUtil aiAuthTokenUtil;
    private final RestTemplate restTemplate;

    @Value("${third-party-ai-store-summary-suggestion.base-url:}")
    private String aiStatisticsAnalysisUrl;

    private static final String DATE_FORMAT = "yyyy-MM-dd";
    private static final String STAT_TYPE_DAILY = "DAILY";

    @Override
    public StoreOperationalStatisticsVo getStatistics(Integer storeId, String startTime, String endTime) {
        log.info("StoreOperationalStatisticsServiceImpl.getStatistics - storeId={}, startTime={}, endTime={}", storeId, startTime, endTime);
        
        // 参数校验
        if (storeId == null || storeId <= 0) {
            throw new IllegalArgumentException("店铺ID不能为空且必须大于0");
        }
        if (startTime == null || startTime.trim().isEmpty()) {
            throw new IllegalArgumentException("开始时间不能为空");
        }
        if (endTime == null || endTime.trim().isEmpty()) {
            throw new IllegalArgumentException("结束时间不能为空");
        }
        
        return calculateStatistics(storeId, startTime, endTime);
    }

    /**
     * 计算统计数据（从store_track_statistics表查询并累加）
     */
    private StoreOperationalStatisticsVo calculateStatistics(Integer storeId, String startTime, String endTime) {
        try {
            // 解析时间范围
            SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
            Date startDate = sdf.parse(startTime);
            Date endDate = sdf.parse(endTime);
            
            // 查询指定时间范围内的日统计数据
            LambdaQueryWrapper<StoreTrackStatistics> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(StoreTrackStatistics::getStoreId, storeId)
                    .eq(StoreTrackStatistics::getStatType, STAT_TYPE_DAILY)
                    .ge(StoreTrackStatistics::getStatDate, startDate)
                    .le(StoreTrackStatistics::getStatDate, endDate);
            
            List<StoreTrackStatistics> statisticsList = storeTrackStatisticsMapper.selectList(wrapper);
            
            if (statisticsList == null || statisticsList.isEmpty()) {
                log.warn("未查询到统计数据 - storeId={}, startTime={}, endTime={}", storeId, startTime, endTime);
                return new StoreOperationalStatisticsVo();
            }
            
            // 聚合统计数据（优先取结束日期的数据，只累加新增访客数）
            return aggregateStatistics(statisticsList, endDate, storeId);
            
        } catch (ParseException e) {
            log.error("StoreOperationalStatisticsServiceImpl.calculateStatistics - 时间解析错误", e);
            throw new RuntimeException("时间格式错误: " + e.getMessage());
        } catch (Exception e) {
            log.error("计算统计数据失败 - storeId={}, startTime={}, endTime={}, error={}", 
                    storeId, startTime, endTime, e.getMessage(), e);
            throw new RuntimeException("计算统计数据失败: " + e.getMessage());
        }
    }
    
    /**
     * 聚合统计数据（优先取结束日期的数据，只累加流量数据中的新增访客数，其他数据取结束日期的记录）
     * 
     * @param statisticsList 统计数据列表
     * @param endDate 结束日期（用于优先选择该日期的数据）
     * @param storeId 店铺ID
     */
    private StoreOperationalStatisticsVo aggregateStatistics(List<StoreTrackStatistics> statisticsList, Date endDate, Integer storeId) {
        StoreOperationalStatisticsVo result = new StoreOperationalStatisticsVo();
        
        // 优先查找结束日期的数据（比较日期部分，忽略时间）
        StoreTrackStatistics endDateStat = null;
        SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
        String endDateStr = sdf.format(endDate);
        for (StoreTrackStatistics stat : statisticsList) {
            if (stat.getStatDate() != null) {
                String statDateStr = sdf.format(stat.getStatDate());
                if (endDateStr.equals(statDateStr)) {
                    endDateStat = stat;
                    break;
                }
            }
        }
        
        // 判断结束日期的数据是否有效（不全为0）
        boolean endDateStatValid = false;
        if (endDateStat != null) {
            endDateStatValid = isStatisticsValid(endDateStat);
        }
        
        // 如果没有结束日期的数据，或者结束日期的数据全是0，则按日期排序，取有数据的最新日期
        StoreTrackStatistics latestStat = null;
        if (endDateStat != null && endDateStatValid) {
            latestStat = endDateStat;
        } else {
            // 按日期排序，从最新到最旧
            statisticsList.sort((a, b) -> {
                if (a.getStatDate() == null && b.getStatDate() == null) return 0;
                if (a.getStatDate() == null) return 1;
                if (b.getStatDate() == null) return -1;
                return b.getStatDate().compareTo(a.getStatDate());
            });
            
            // 查找第一个有数据的记录
            for (StoreTrackStatistics stat : statisticsList) {
                if (isStatisticsValid(stat)) {
                    latestStat = stat;
                    break;
                }
            }
            
            // 如果所有记录都无效，使用最新的记录（即使全是0）
            if (latestStat == null && !statisticsList.isEmpty()) {
                latestStat = statisticsList.get(0);
            }
            
            if (latestStat != null) {
                if (endDateStat != null && !endDateStatValid) {
                    log.info("结束日期{}的数据全是0，使用范围内有数据的最新日期{}的数据", 
                            endDateStr,
                            latestStat.getStatDate() != null ? sdf.format(latestStat.getStatDate()) : "未知");
                } else {
                    log.info("结束日期{}没有统计数据，使用范围内最新日期{}的数据", 
                            endDateStr,
                            latestStat.getStatDate() != null ? sdf.format(latestStat.getStatDate()) : "未知");
                }
            }
        }
        
        // 如果找不到有效数据，返回空结果
        if (latestStat == null) {
            log.warn("未找到有效的统计数据，返回空结果");
            return result;
        }
        
        // 只累加流量数据中的新增访客数
        long newVisitorCountSum = 0L;
        for (StoreTrackStatistics stat : statisticsList) {
            if (stat.getTrafficData() != null && !stat.getTrafficData().isEmpty()) {
                try {
                    Map<String, Object> trafficData = (Map<String, Object>) JSON.parseObject(stat.getTrafficData(), Map.class);
                    if (trafficData != null && trafficData.containsKey("newVisitorCount")) {
                        newVisitorCountSum += getLongValue(trafficData, "newVisitorCount");
                    }
                } catch (Exception e) {
                    log.warn("解析流量数据失败: {}", stat.getTrafficData(), e);
                }
            }
        }
        
        // 使用最新记录的数据，但替换新增访客数为累加值
        if (latestStat.getTrafficData() != null && !latestStat.getTrafficData().isEmpty()) {
            try {
                Map<String, Object> latestTrafficData = (Map<String, Object>) JSON.parseObject(latestStat.getTrafficData(), Map.class);
                if (latestTrafficData != null) {
                    latestTrafficData.put("newVisitorCount", newVisitorCountSum);
                    result.setTrafficData(convertToTrafficDataVoFromMap(latestTrafficData));
                }
            } catch (Exception e) {
                log.warn("解析最新流量数据失败: {}", latestStat.getTrafficData(), e);
            }
        }
        
        // 其他数据直接使用最新记录的值
        if (latestStat.getInteractionData() != null && !latestStat.getInteractionData().isEmpty()) {
            result.setInteractionData(convertToInteractionDataVoFromJson(latestStat.getInteractionData()));
        }
        
        if (latestStat.getCouponData() != null && !latestStat.getCouponData().isEmpty()) {
            result.setCouponData(convertToCouponDataVoFromJson(latestStat.getCouponData()));
        }
        
        if (latestStat.getVoucherData() != null && !latestStat.getVoucherData().isEmpty()) {
            result.setVoucherData(convertToVoucherDataVoFromJson(latestStat.getVoucherData()));
        }
        
        if (latestStat.getServiceData() != null && !latestStat.getServiceData().isEmpty()) {
            result.setServiceQualityData(convertToServiceQualityDataVoFromJson(latestStat.getServiceData()));
        }
        
        if (latestStat.getPriceRankingData() != null && !latestStat.getPriceRankingData().isEmpty()) {
            result.setPriceListRanking(convertToPriceListRankingVoFromJson(latestStat.getPriceRankingData(), storeId));
        }
        
        return result;
    }

    @Override
    public StoreOperationalStatisticsComparisonVo getStatisticsComparison(Integer storeId, String currentStartTime, String currentEndTime,
                                                                          String previousStartTime, String previousEndTime) {
        log.info("StoreOperationalStatisticsServiceImpl.getStatisticsComparison - storeId={}, currentStartTime={}, currentEndTime={}, previousStartTime={}, previousEndTime={}",
                storeId, currentStartTime, currentEndTime, previousStartTime, previousEndTime);

        // 参数校验
        if (storeId == null || storeId <= 0) {
            throw new IllegalArgumentException("店铺ID不能为空且必须大于0");
        }
        if (currentStartTime == null || currentStartTime.trim().isEmpty()) {
            throw new IllegalArgumentException("当期开始时间不能为空");
        }
        if (currentEndTime == null || currentEndTime.trim().isEmpty()) {
            throw new IllegalArgumentException("当期结束时间不能为空");
        }
        if (previousStartTime == null || previousStartTime.trim().isEmpty()) {
            throw new IllegalArgumentException("上期开始时间不能为空");
        }
        if (previousEndTime == null || previousEndTime.trim().isEmpty()) {
            throw new IllegalArgumentException("上期结束时间不能为空");
        }

        StoreOperationalStatisticsComparisonVo comparison = new StoreOperationalStatisticsComparisonVo();
        comparison.setCurrentStartTime(currentStartTime);
        comparison.setCurrentEndTime(currentEndTime);
        comparison.setPreviousStartTime(previousStartTime);
        comparison.setPreviousEndTime(previousEndTime);

        // 获取当期和上期的统计数据
        StoreOperationalStatisticsVo currentStatistics = calculateStatistics(storeId, currentStartTime, currentEndTime);
        StoreOperationalStatisticsVo previousStatistics = calculateStatistics(storeId, previousStartTime, previousEndTime);

        // 构建对比数据
        comparison.setTrafficData(buildTrafficDataComparison(currentStatistics.getTrafficData(), previousStatistics.getTrafficData()));
        comparison.setInteractionData(buildInteractionDataComparison(currentStatistics.getInteractionData(), previousStatistics.getInteractionData()));
        comparison.setCouponData(buildCouponDataComparison(currentStatistics.getCouponData(), previousStatistics.getCouponData()));
        comparison.setVoucherData(buildVoucherDataComparison(currentStatistics.getVoucherData(), previousStatistics.getVoucherData()));
        comparison.setServiceQualityData(buildServiceQualityDataComparison(currentStatistics.getServiceQualityData(), previousStatistics.getServiceQualityData()));
        comparison.setPriceListRanking(buildPriceListRankingComparison(currentStatistics.getPriceListRanking(), previousStatistics.getPriceListRanking(), storeId));

        // 保存历史记录（不包含PDF URL，PDF URL只在 generateStatisticsComparisonPdf 接口中保存）
        Integer historyId = saveStatisticsHistory(storeId, currentStartTime, currentEndTime, 
                previousStartTime, previousEndTime, comparison, null);

        // 将历史记录ID设置到返回对象中
        comparison.setHistoryId(historyId);

        // 异步调用AI接口进行数据分析
        if (historyId != null) {
            try {
                callAiAnalysisAsync(historyId, storeId, comparison);
            } catch (Exception e) {
                log.error("调用AI分析接口失败 - historyId={}, error={}", historyId, e.getMessage(), e);
                // AI分析失败不影响主流程，只记录日志
            }
        }

        return comparison;
    }

    @Override
    public boolean getStatisticsComparisonNew(Integer storeId, String currentStartTime, String currentEndTime,
                                             String previousStartTime, String previousEndTime) {
        log.info("StoreOperationalStatisticsServiceImpl.getStatisticsComparisonNew - storeId={}, currentStartTime={}, currentEndTime={}, previousStartTime={}, previousEndTime={}",
                storeId, currentStartTime, currentEndTime, previousStartTime, previousEndTime);

        // 参数校验
        if (storeId == null || storeId <= 0) {
            throw new IllegalArgumentException("店铺ID不能为空且必须大于0");
        }
        if (currentStartTime == null || currentStartTime.trim().isEmpty()) {
            throw new IllegalArgumentException("当期开始时间不能为空");
        }
        if (currentEndTime == null || currentEndTime.trim().isEmpty()) {
            throw new IllegalArgumentException("当期结束时间不能为空");
        }
        if (previousStartTime == null || previousStartTime.trim().isEmpty()) {
            throw new IllegalArgumentException("上期开始时间不能为空");
        }
        if (previousEndTime == null || previousEndTime.trim().isEmpty()) {
            throw new IllegalArgumentException("上期结束时间不能为空");
        }

        StoreOperationalStatisticsComparisonVo comparison = new StoreOperationalStatisticsComparisonVo();
        comparison.setCurrentStartTime(currentStartTime);
        comparison.setCurrentEndTime(currentEndTime);
        comparison.setPreviousStartTime(previousStartTime);
        comparison.setPreviousEndTime(previousEndTime);

        // 获取当期和上期的统计数据
        StoreOperationalStatisticsVo currentStatistics = calculateStatistics(storeId, currentStartTime, currentEndTime);
        StoreOperationalStatisticsVo previousStatistics = calculateStatistics(storeId, previousStartTime, previousEndTime);

        // 构建对比数据
        comparison.setTrafficData(buildTrafficDataComparison(currentStatistics.getTrafficData(), previousStatistics.getTrafficData()));
        comparison.setInteractionData(buildInteractionDataComparison(currentStatistics.getInteractionData(), previousStatistics.getInteractionData()));
        comparison.setCouponData(buildCouponDataComparison(currentStatistics.getCouponData(), previousStatistics.getCouponData()));
        comparison.setVoucherData(buildVoucherDataComparison(currentStatistics.getVoucherData(), previousStatistics.getVoucherData()));
        comparison.setServiceQualityData(buildServiceQualityDataComparison(currentStatistics.getServiceQualityData(), previousStatistics.getServiceQualityData()));
        comparison.setPriceListRanking(buildPriceListRankingComparison(currentStatistics.getPriceListRanking(), previousStatistics.getPriceListRanking(), storeId));

        // 当comparison中所有对比数据的current和previous都为0或为空时，返回 false（失败）
        if (!hasComparisonData(comparison)) {
            return false;
        }
        return true;
    }

    /**
     * 将StoreOperationalStatisticsVo转换为符合埋点统计数据JSON格式
     */
    private Map<String, Object> convertToTrackStatisticsFormat(StoreOperationalStatisticsVo statistics) {
        Map<String, Object> result = new HashMap<>();
        
        // 1. 转换流量数据
        if (statistics.getTrafficData() != null) {
            StoreOperationalStatisticsVo.TrafficData traffic = statistics.getTrafficData();
            Map<String, Object> trafficData = new HashMap<>();
            trafficData.put("searchCount", traffic.getStoreSearchVolume() != null ? traffic.getStoreSearchVolume() : 0L);
            trafficData.put("viewCount", traffic.getPageViews() != null ? traffic.getPageViews() : 0L);
            trafficData.put("visitorCount", traffic.getVisitors() != null ? traffic.getVisitors() : 0L);
            trafficData.put("newVisitorCount", traffic.getNewVisitors() != null ? traffic.getNewVisitors() : 0L);
            // 访问时长从秒转换为毫秒
            trafficData.put("totalDuration", traffic.getVisitDuration() != null ? traffic.getVisitDuration() * 1000 : 0L);
            trafficData.put("avgDuration", traffic.getAvgVisitDuration() != null ? traffic.getAvgVisitDuration() * 1000 : 0L);
            result.put("trafficData", trafficData);
        }
        
        // 2. 转换互动数据
        if (statistics.getInteractionData() != null) {
            StoreOperationalStatisticsVo.InteractionData interaction = statistics.getInteractionData();
            Map<String, Object> interactionData = new HashMap<>();
            interactionData.put("collectCount", interaction.getStoreCollectionCount() != null ? interaction.getStoreCollectionCount() : 0L);
            interactionData.put("shareCount", interaction.getStoreShareCount() != null ? interaction.getStoreShareCount() : 0L);
            interactionData.put("checkinCount", interaction.getStoreCheckInCount() != null ? interaction.getStoreCheckInCount() : 0L);
            interactionData.put("consultCount", interaction.getConsultMerchantCount() != null ? interaction.getConsultMerchantCount() : 0L);
            interactionData.put("friendCount", interaction.getFriendsCount() != null ? interaction.getFriendsCount() : 0L);
            interactionData.put("followCount", interaction.getFollowCount() != null ? interaction.getFollowCount() : 0L);
            interactionData.put("fansCount", interaction.getFansCount() != null ? interaction.getFansCount() : 0L);
            interactionData.put("postCount", interaction.getPostsPublishedCount() != null ? interaction.getPostsPublishedCount() : 0L);
            interactionData.put("postLikeCount", interaction.getPostLikesCount() != null ? interaction.getPostLikesCount() : 0L);
            interactionData.put("postCommentCount", interaction.getPostCommentsCount() != null ? interaction.getPostCommentsCount() : 0L);
            interactionData.put("postRepostCount", interaction.getPostSharesCount() != null ? interaction.getPostSharesCount() : 0L);
            interactionData.put("reportCount", interaction.getReportedCount() != null ? interaction.getReportedCount() : 0L);
            interactionData.put("blockCount", interaction.getBlockedCount() != null ? interaction.getBlockedCount() : 0L);
            result.put("interactionData", interactionData);
        }
        
        // 3. 转换优惠券数据
        if (statistics.getCouponData() != null) {
            StoreOperationalStatisticsVo.CouponData coupon = statistics.getCouponData();
            Map<String, Object> couponData = new HashMap<>();
            couponData.put("giveToFriendCount", coupon.getGiftToFriendsCount() != null ? coupon.getGiftToFriendsCount() : 0L);
            couponData.put("giveToFriendAmount", coupon.getGiftToFriendsAmount() != null ? coupon.getGiftToFriendsAmount() : BigDecimal.ZERO);
            couponData.put("giveToFriendUseCount", coupon.getGiftToFriendsUsedCount() != null ? coupon.getGiftToFriendsUsedCount() : 0L);
            couponData.put("giveToFriendUseAmount", coupon.getGiftToFriendsUsedAmount() != null ? coupon.getGiftToFriendsUsedAmount() : BigDecimal.ZERO);
            // 百分比转换：BigDecimal -> Double
            if (coupon.getGiftToFriendsUsedAmountRatio() != null) {
                couponData.put("giveToFriendUseAmountPercent", coupon.getGiftToFriendsUsedAmountRatio().doubleValue());
            } else {
                couponData.put("giveToFriendUseAmountPercent", 0.0);
            }
            couponData.put("friendGiveCount", coupon.getFriendsGiftCount() != null ? coupon.getFriendsGiftCount() : 0L);
            couponData.put("friendGiveAmount", coupon.getFriendsGiftAmount() != null ? coupon.getFriendsGiftAmount() : BigDecimal.ZERO);
            couponData.put("friendGiveUseCount", coupon.getFriendsGiftUsedCount() != null ? coupon.getFriendsGiftUsedCount() : 0L);
            couponData.put("friendGiveUseAmount", coupon.getFriendsGiftUsedAmount() != null ? coupon.getFriendsGiftUsedAmount() : BigDecimal.ZERO);
            if (coupon.getFriendsGiftUsedAmountRatio() != null) {
                couponData.put("friendGiveUseAmountPercent", coupon.getFriendsGiftUsedAmountRatio().doubleValue());
            } else {
                couponData.put("friendGiveUseAmountPercent", 0.0);
            }
            result.put("couponData", couponData);
        }
        
        // 4. 转换代金券数据
        if (statistics.getVoucherData() != null) {
            StoreOperationalStatisticsVo.VoucherData voucher = statistics.getVoucherData();
            Map<String, Object> voucherData = new HashMap<>();
            voucherData.put("giveToFriendCount", voucher.getGiftToFriendsCount() != null ? voucher.getGiftToFriendsCount() : 0L);
            voucherData.put("giveToFriendAmount", voucher.getGiftToFriendsAmount() != null ? voucher.getGiftToFriendsAmount() : BigDecimal.ZERO);
            voucherData.put("giveToFriendUseCount", voucher.getGiftToFriendsUsedCount() != null ? voucher.getGiftToFriendsUsedCount() : 0L);
            voucherData.put("giveToFriendUseAmount", voucher.getGiftToFriendsUsedAmount() != null ? voucher.getGiftToFriendsUsedAmount() : BigDecimal.ZERO);
            if (voucher.getGiftToFriendsUsedAmountRatio() != null) {
                voucherData.put("giveToFriendUseAmountPercent", voucher.getGiftToFriendsUsedAmountRatio().doubleValue());
            } else {
                voucherData.put("giveToFriendUseAmountPercent", 0.0);
            }
            voucherData.put("friendGiveCount", voucher.getFriendsGiftCount() != null ? voucher.getFriendsGiftCount() : 0L);
            voucherData.put("friendGiveAmount", voucher.getFriendsGiftAmount() != null ? voucher.getFriendsGiftAmount() : BigDecimal.ZERO);
            voucherData.put("friendGiveUseCount", voucher.getFriendsGiftUsedCount() != null ? voucher.getFriendsGiftUsedCount() : 0L);
            voucherData.put("friendGiveUseAmount", voucher.getFriendsGiftUsedAmount() != null ? voucher.getFriendsGiftUsedAmount() : BigDecimal.ZERO);
            if (voucher.getFriendsGiftUsedAmountRatio() != null) {
                voucherData.put("friendGiveUseAmountPercent", voucher.getFriendsGiftUsedAmountRatio().doubleValue());
            } else {
                voucherData.put("friendGiveUseAmountPercent", 0.0);
            }
            result.put("voucherData", voucherData);
        }
        
        // 5. 转换服务质量数据
        if (statistics.getServiceQualityData() != null) {
            StoreOperationalStatisticsVo.ServiceQualityData service = statistics.getServiceQualityData();
            Map<String, Object> serviceData = new HashMap<>();
            serviceData.put("storeScore", service.getStoreRating() != null ? service.getStoreRating().doubleValue() : 0.0);
            serviceData.put("scoreOne", service.getScoreOne() != null ? service.getScoreOne().doubleValue() : 0.0);
            serviceData.put("scoreTwo", service.getScoreTwo() != null ? service.getScoreTwo().doubleValue() : 0.0);
            serviceData.put("scoreThree", service.getScoreThree() != null ? service.getScoreThree().doubleValue() : 0.0);
            serviceData.put("ratingCount", service.getTotalReviews() != null ? service.getTotalReviews() : 0L);
            serviceData.put("goodRatingCount", service.getPositiveReviews() != null ? service.getPositiveReviews() : 0L);
            serviceData.put("midRatingCount", service.getNeutralReviews() != null ? service.getNeutralReviews() : 0L);
            serviceData.put("badRatingCount", service.getNegativeReviews() != null ? service.getNegativeReviews() : 0L);
            if (service.getNegativeReviewRatio() != null) {
                serviceData.put("badRatingPercent", service.getNegativeReviewRatio().doubleValue());
            } else {
                serviceData.put("badRatingPercent", 0.0);
            }
            serviceData.put("appealCount", service.getNegativeReviewAppealsCount() != null ? service.getNegativeReviewAppealsCount() : 0L);
            serviceData.put("appealSuccessCount", service.getNegativeReviewAppealsSuccessCount() != null ? service.getNegativeReviewAppealsSuccessCount() : 0L);
            if (service.getNegativeReviewAppealsSuccessRatio() != null) {
                serviceData.put("appealSuccessPercent", service.getNegativeReviewAppealsSuccessRatio().doubleValue());
            } else {
                serviceData.put("appealSuccessPercent", 0.0);
            }
            result.put("serviceData", serviceData);
        }
        
        // 6. 转换价目表排名数据
        if (statistics.getPriceListRanking() != null && !statistics.getPriceListRanking().isEmpty()) {
            List<Map<String, Object>> priceRankingData = new ArrayList<>();
            for (StoreOperationalStatisticsVo.PriceListRanking ranking : statistics.getPriceListRanking()) {
                Map<String, Object> priceItem = new HashMap<>();
                priceItem.put("priceId", ranking.getPriceId() != null ? ranking.getPriceId() : 0);
                priceItem.put("viewCount", ranking.getPageViews() != null ? ranking.getPageViews().intValue() : 0);
                priceItem.put("visitorCount", ranking.getVisitors() != null ? ranking.getVisitors().intValue() : 0);
                priceItem.put("shareCount", ranking.getShares() != null ? ranking.getShares().intValue() : 0);
                priceRankingData.add(priceItem);
            }
            result.put("priceRankingData", priceRankingData);
        } else {
            result.put("priceRankingData", new ArrayList<>());
        }
        
        return result;
    }

    /**
     * 获取流量数据
     */
    private StoreOperationalStatisticsVo.TrafficData getTrafficData(Integer storeId, Date startDate, Date endDate) {
        StoreOperationalStatisticsVo.TrafficData trafficData = new StoreOperationalStatisticsVo.TrafficData();

        // TODO: 实现店铺搜索量统计（需要根据实际业务逻辑查询搜索记录表）
        trafficData.setStoreSearchVolume(0L);

        // 浏览记录统计
        LambdaQueryWrapper<LifeBrowseRecord> browseWrapper = new LambdaQueryWrapper<>();
        if (storeId != null) {
            browseWrapper.eq(LifeBrowseRecord::getStoreId, String.valueOf(storeId));
        }
        browseWrapper.between(LifeBrowseRecord::getCreatedTime, startDate, endDate)
                .eq(LifeBrowseRecord::getDeleteFlag, 0);
        List<LifeBrowseRecord> browseRecords = lifeBrowseRecordMapper.selectList(browseWrapper);

        // 浏览量
        trafficData.setPageViews((long) browseRecords.size());

        // 访客数（去重用户ID）
        long visitors = browseRecords.stream()
                .map(LifeBrowseRecord::getUserId)
                .distinct()
                .count();
        trafficData.setVisitors(visitors);

        // TODO: 新增访客数统计（需要对比历史数据判断是否为新访客）
        trafficData.setNewVisitors(0L);

        // TODO: 访问时长统计（需要根据实际业务逻辑计算）
        trafficData.setVisitDuration(0L);

        // TODO: 平均访问时长统计
        trafficData.setAvgVisitDuration(0L);

        return trafficData;
    }

    /**
     * 获取互动数据
     */
    private StoreOperationalStatisticsVo.InteractionData getInteractionData(Integer storeId, Date startDate, Date endDate) {
        StoreOperationalStatisticsVo.InteractionData interactionData = new StoreOperationalStatisticsVo.InteractionData();

        // 收藏次数
        LambdaQueryWrapper<LifeCollect> collectWrapper = new LambdaQueryWrapper<>();
        if (storeId != null) {
            collectWrapper.eq(LifeCollect::getStoreId, String.valueOf(storeId));
        }
        collectWrapper.between(LifeCollect::getCreatedTime, startDate, endDate)
                .eq(LifeCollect::getDeleteFlag, 0);
        long collectionCount = lifeCollectMapper.selectCount(collectWrapper);
        interactionData.setStoreCollectionCount(collectionCount);

        // TODO: 分享次数统计（需要根据实际业务逻辑查询分享记录表）
        interactionData.setStoreShareCount(0L);

        // 打卡次数
        LambdaQueryWrapper<StoreClockIn> clockInWrapper = new LambdaQueryWrapper<>();
        clockInWrapper.eq(StoreClockIn::getStoreId, storeId)
                .between(StoreClockIn::getCreatedTime, startDate, endDate);
        long checkInCount = storeClockInMapper.selectCount(clockInWrapper);
        interactionData.setStoreCheckInCount(checkInCount);

        // TODO: 咨询商家次数统计（需要根据实际业务逻辑查询咨询记录表）
        interactionData.setConsultMerchantCount(0L);

        // 好友数量（店铺好友关系）
        // TODO: 需要根据实际业务逻辑查询好友关系表
        interactionData.setFriendsCount(0L);

        // 关注数量
        // TODO: 需要根据实际业务逻辑查询关注关系（需要确认店铺的关注关系表结构）
        // LambdaQueryWrapper<LifeFans> fansWrapper = new LambdaQueryWrapper<>();
        interactionData.setFollowCount(0L);

        // 粉丝数量
        // TODO: 需要根据实际业务逻辑查询粉丝关系
        interactionData.setFansCount(0L);

        // 动态相关统计（店铺发布的动态）
        StoreUser storeUser = storeUserMapper.selectOne(
                new LambdaQueryWrapper<StoreUser>().eq(StoreUser::getStoreId, storeId).last("LIMIT 1"));
        if (storeUser != null) {
            LambdaQueryWrapper<LifeUserDynamics> dynamicsWrapper = new LambdaQueryWrapper<>();
            dynamicsIdentityHelper.applyPublisherFilter(dynamicsWrapper,
                    new LifeDynamicsIdentityHelper.PublisherScope(
                            "store_" + storeUser.getPhone(),
                            LifeDynamicsIdentityHelper.TYPE_STORE,
                            storeUser.getId()));
            dynamicsWrapper.between(LifeUserDynamics::getCreatedTime, startDate, endDate)
                    .eq(LifeUserDynamics::getDeleteFlag, 0)
                    .eq(LifeUserDynamics::getDraft, 0);
            long postsCount = lifeUserDynamicsMapper.selectCount(dynamicsWrapper);
            interactionData.setPostsPublishedCount(postsCount);

            // 动态点赞数量
            List<LifeUserDynamics> dynamicsList = lifeUserDynamicsMapper.selectList(dynamicsWrapper);
            long likesCount = dynamicsList.stream()
                    .mapToLong(d -> d.getDianzanCount() != null ? d.getDianzanCount() : 0L)
                    .sum();
            interactionData.setPostLikesCount(likesCount);

            // 动态评论数量
            long commentsCount = 0L;
            for (LifeUserDynamics dynamics : dynamicsList) {
                LambdaQueryWrapper<StoreComment> commentWrapper = new LambdaQueryWrapper<>();
                commentWrapper.eq(StoreComment::getBusinessId, String.valueOf(dynamics.getId()))
                        .eq(StoreComment::getBusinessType, 2)
                        .eq(StoreComment::getDeleteFlag, 0);
                commentsCount += storeCommentMapper.selectCount(commentWrapper);
            }
            interactionData.setPostCommentsCount(commentsCount);

            // 动态转发数量
            long sharesCount = dynamicsList.stream()
                    .mapToLong(d -> d.getTransferCount() != null ? d.getTransferCount() : 0L)
                    .sum();
            interactionData.setPostSharesCount(sharesCount);
        } else {
            interactionData.setPostsPublishedCount(0L);
            interactionData.setPostLikesCount(0L);
            interactionData.setPostCommentsCount(0L);
            interactionData.setPostSharesCount(0L);
        }

        // TODO: 被举报次数统计
        interactionData.setReportedCount(0L);

        // 被拉黑次数
        // TODO: 需要根据实际业务逻辑查询拉黑记录
        interactionData.setBlockedCount(0L);

        return interactionData;
    }

    /**
     * 获取优惠券数据
     */
    private StoreOperationalStatisticsVo.CouponData getCouponData(Integer storeId, Date startDate, Date endDate) {
        StoreOperationalStatisticsVo.CouponData couponData = new StoreOperationalStatisticsVo.CouponData();

        // TODO: 实现优惠券相关统计
        // 1. 赠送好友数量
        // 2. 赠送好友金额合计
        // 3. 赠送好友使用数量
        // 4. 赠送好友使用金额合计
        // 5. 好友赠送数量
        // 6. 好友赠送金额合计
        // 7. 好友赠送使用数量
        // 8. 好友赠送使用金额合计

        // TODO: 根据实际业务逻辑查询 life_discount_coupon_store_friend 表
        // 注意：LifeDiscountCouponStoreFriend 没有 storeId 字段，需要通过 storeUserId 关联查询
        // LambdaQueryWrapper<LifeDiscountCouponStoreFriend> friendCouponWrapper = new LambdaQueryWrapper<>();
        // friendCouponWrapper.eq(LifeDiscountCouponStoreFriend::getStoreUserId, storeUserId)
        //         .between(LifeDiscountCouponStoreFriend::getCreatedTime, startDate, endDate);
        // TODO: 需要根据实际业务逻辑完善统计

        couponData.setGiftToFriendsCount(0L);
        couponData.setGiftToFriendsAmount(BigDecimal.ZERO);
        couponData.setGiftToFriendsUsedCount(0L);
        couponData.setGiftToFriendsUsedAmount(BigDecimal.ZERO);
        couponData.setGiftToFriendsUsedAmountRatio(BigDecimal.ZERO);
        couponData.setFriendsGiftCount(0L);
        couponData.setFriendsGiftAmount(BigDecimal.ZERO);
        couponData.setFriendsGiftUsedCount(0L);
        couponData.setFriendsGiftUsedAmount(BigDecimal.ZERO);
        couponData.setFriendsGiftUsedAmountRatio(BigDecimal.ZERO);

        return couponData;
    }

    /**
     * 获取代金券数据（与优惠券类似，根据实际业务区分）
     */
    private StoreOperationalStatisticsVo.VoucherData getVoucherData(Integer storeId, Date startDate, Date endDate) {
        StoreOperationalStatisticsVo.VoucherData voucherData = new StoreOperationalStatisticsVo.VoucherData();

        // TODO: 实现代金券相关统计（与优惠券逻辑类似）
        voucherData.setGiftToFriendsCount(0L);
        voucherData.setGiftToFriendsAmount(BigDecimal.ZERO);
        voucherData.setGiftToFriendsUsedCount(0L);
        voucherData.setGiftToFriendsUsedAmount(BigDecimal.ZERO);
        voucherData.setGiftToFriendsUsedAmountRatio(BigDecimal.ZERO);
        voucherData.setFriendsGiftCount(0L);
        voucherData.setFriendsGiftAmount(BigDecimal.ZERO);
        voucherData.setFriendsGiftUsedCount(0L);
        voucherData.setFriendsGiftUsedAmount(BigDecimal.ZERO);
        voucherData.setFriendsGiftUsedAmountRatio(BigDecimal.ZERO);

        return voucherData;
    }

    /**
     * 获取服务质量数据
     */
    private StoreOperationalStatisticsVo.ServiceQualityData getServiceQualityData(Integer storeId, Date startDate, Date endDate) {
        StoreOperationalStatisticsVo.ServiceQualityData serviceQualityData = new StoreOperationalStatisticsVo.ServiceQualityData();

        // 查询评价数据（StoreEvaluation）
        LambdaQueryWrapper<StoreEvaluation> evaluationWrapper = new LambdaQueryWrapper<>();
        evaluationWrapper.eq(StoreEvaluation::getStoreId, storeId)
                .between(StoreEvaluation::getCreatedTime, startDate, endDate);
        List<StoreEvaluation> evaluations = storeEvaluationMapper.selectList(evaluationWrapper);

        if (!evaluations.isEmpty()) {
            // 计算平均评分
            double avgScore = evaluations.stream()
                    .mapToDouble(e -> e.getScore() != null ? e.getScore().doubleValue() : 0.0)
                    .average()
                    .orElse(0.0);
            serviceQualityData.setStoreRating(BigDecimal.valueOf(avgScore).setScale(1, RoundingMode.HALF_UP));

            // TODO: 评分1、评分2、评分3需要根据评价详情表查询
            serviceQualityData.setScoreOne(BigDecimal.ZERO);
            serviceQualityData.setScoreTwo(BigDecimal.ZERO);
            serviceQualityData.setScoreThree(BigDecimal.ZERO);

            // 评价数量
            serviceQualityData.setTotalReviews((long) evaluations.size());

            // 好评、中评、差评统计（StoreEvaluation.score 是 Double 类型）
            long positiveCount = evaluations.stream()
                    .filter(e -> e.getScore() != null && e.getScore() >= 4.5)
                    .count();
            long neutralCount = evaluations.stream()
                    .filter(e -> e.getScore() != null && e.getScore() >= 3.5 && e.getScore() < 4.5)
                    .count();
            long negativeCount = evaluations.stream()
                    .filter(e -> e.getScore() != null && e.getScore() < 3.5)
                    .count();

            serviceQualityData.setPositiveReviews(positiveCount);
            serviceQualityData.setNeutralReviews(neutralCount);
            serviceQualityData.setNegativeReviews(negativeCount);

            // 差评占比
            if (evaluations.size() > 0) {
                BigDecimal ratio = BigDecimal.valueOf(negativeCount)
                        .divide(BigDecimal.valueOf(evaluations.size()), 4, RoundingMode.HALF_UP)
                        .multiply(BigDecimal.valueOf(100));
                serviceQualityData.setNegativeReviewRatio(ratio.setScale(2, RoundingMode.HALF_UP));
            } else {
                serviceQualityData.setNegativeReviewRatio(BigDecimal.ZERO);
            }

            // 差评申诉相关统计
            // TODO: 需要查询差评申诉表 StoreCommentAppeal
            serviceQualityData.setNegativeReviewAppealsCount(0L);
            serviceQualityData.setNegativeReviewAppealsSuccessCount(0L);
            serviceQualityData.setNegativeReviewAppealsSuccessRatio(BigDecimal.ZERO);
        } else {
            serviceQualityData.setStoreRating(BigDecimal.ZERO);
            serviceQualityData.setScoreOne(BigDecimal.ZERO);
            serviceQualityData.setScoreTwo(BigDecimal.ZERO);
            serviceQualityData.setScoreThree(BigDecimal.ZERO);
            serviceQualityData.setTotalReviews(0L);
            serviceQualityData.setPositiveReviews(0L);
            serviceQualityData.setNeutralReviews(0L);
            serviceQualityData.setNegativeReviews(0L);
            serviceQualityData.setNegativeReviewRatio(BigDecimal.ZERO);
            serviceQualityData.setNegativeReviewAppealsCount(0L);
            serviceQualityData.setNegativeReviewAppealsSuccessCount(0L);
            serviceQualityData.setNegativeReviewAppealsSuccessRatio(BigDecimal.ZERO);
        }

        return serviceQualityData;
    }

    /**
     * 获取价目表排名数据
     */
    private List<StoreOperationalStatisticsVo.PriceListRanking> getPriceListRanking(Integer storeId, Date startDate, Date endDate) {
        List<StoreOperationalStatisticsVo.PriceListRanking> rankings = new ArrayList<>();

        // TODO: 实现价目表排名统计
        // 需要查询价目表（StorePrice）的浏览量、访客数、分享数等

        LambdaQueryWrapper<StorePrice> priceWrapper = new LambdaQueryWrapper<>();
        priceWrapper.eq(StorePrice::getStoreId, storeId);
        List<StorePrice> prices = storePriceMapper.selectList(priceWrapper);

        // TODO: 需要根据浏览记录统计每个价目表的浏览量和访客数
        // 示例逻辑（需要根据实际业务完善）
        int rank = 1;
        for (StorePrice price : prices) {
            StoreOperationalStatisticsVo.PriceListRanking ranking = new StoreOperationalStatisticsVo.PriceListRanking();
            ranking.setRank(rank++);
            ranking.setPriceId(price.getId());
            ranking.setPriceListItemName(price.getName());
            // TODO: 统计该价目表的浏览量、访客数、分享数
            ranking.setPageViews(0L);
            ranking.setVisitors(0L);
            ranking.setShares(0L);
            rankings.add(ranking);
        }

        return rankings;
    }

    /**
     * 构建流量数据对比
     */
    private StoreOperationalStatisticsComparisonVo.TrafficDataComparison buildTrafficDataComparison(
            StoreOperationalStatisticsVo.TrafficData current, StoreOperationalStatisticsVo.TrafficData previous) {
        StoreOperationalStatisticsComparisonVo.TrafficDataComparison comparison = new StoreOperationalStatisticsComparisonVo.TrafficDataComparison();
        // 如果 previous 为 null，创建空对象避免 NullPointerException
        if (previous == null) {
            previous = new StoreOperationalStatisticsVo.TrafficData();
        }
        if (current == null) {
            current = new StoreOperationalStatisticsVo.TrafficData();
        }
        comparison.setStoreSearchVolume(buildComparisonData(current.getStoreSearchVolume(), previous.getStoreSearchVolume()));
        comparison.setPageViews(buildComparisonData(current.getPageViews(), previous.getPageViews()));
        comparison.setVisitors(buildComparisonData(current.getVisitors(), previous.getVisitors()));
        comparison.setNewVisitors(buildComparisonData(current.getNewVisitors(), previous.getNewVisitors()));
        comparison.setVisitDuration(buildComparisonData(current.getVisitDuration(), previous.getVisitDuration()));
        comparison.setAvgVisitDuration(buildComparisonData(current.getAvgVisitDuration(), previous.getAvgVisitDuration()));
        return comparison;
    }

    /**
     * 构建互动数据对比
     */
    private StoreOperationalStatisticsComparisonVo.InteractionDataComparison buildInteractionDataComparison(
            StoreOperationalStatisticsVo.InteractionData current, StoreOperationalStatisticsVo.InteractionData previous) {
        StoreOperationalStatisticsComparisonVo.InteractionDataComparison comparison = new StoreOperationalStatisticsComparisonVo.InteractionDataComparison();
        // 如果 previous 为 null，创建空对象避免 NullPointerException
        if (previous == null) {
            previous = new StoreOperationalStatisticsVo.InteractionData();
        }
        if (current == null) {
            current = new StoreOperationalStatisticsVo.InteractionData();
        }
        comparison.setStoreCollectionCount(buildComparisonData(current.getStoreCollectionCount(), previous.getStoreCollectionCount()));
        comparison.setStoreShareCount(buildComparisonData(current.getStoreShareCount(), previous.getStoreShareCount()));
        comparison.setStoreCheckInCount(buildComparisonData(current.getStoreCheckInCount(), previous.getStoreCheckInCount()));
        comparison.setConsultMerchantCount(buildComparisonData(current.getConsultMerchantCount(), previous.getConsultMerchantCount()));
        comparison.setFriendsCount(buildComparisonData(current.getFriendsCount(), previous.getFriendsCount()));
        comparison.setFollowCount(buildComparisonData(current.getFollowCount(), previous.getFollowCount()));
        comparison.setFansCount(buildComparisonData(current.getFansCount(), previous.getFansCount()));
        comparison.setPostsPublishedCount(buildComparisonData(current.getPostsPublishedCount(), previous.getPostsPublishedCount()));
        comparison.setPostLikesCount(buildComparisonData(current.getPostLikesCount(), previous.getPostLikesCount()));
        comparison.setPostCommentsCount(buildComparisonData(current.getPostCommentsCount(), previous.getPostCommentsCount()));
        comparison.setPostSharesCount(buildComparisonData(current.getPostSharesCount(), previous.getPostSharesCount()));
        comparison.setReportedCount(buildComparisonData(current.getReportedCount(), previous.getReportedCount()));
        comparison.setBlockedCount(buildComparisonData(current.getBlockedCount(), previous.getBlockedCount()));
        return comparison;
    }

    /**
     * 构建优惠券数据对比
     */
    private StoreOperationalStatisticsComparisonVo.CouponDataComparison buildCouponDataComparison(
            StoreOperationalStatisticsVo.CouponData current, StoreOperationalStatisticsVo.CouponData previous) {
        StoreOperationalStatisticsComparisonVo.CouponDataComparison comparison = new StoreOperationalStatisticsComparisonVo.CouponDataComparison();
        // 如果 previous 为 null，创建空对象避免 NullPointerException
        if (previous == null) {
            previous = new StoreOperationalStatisticsVo.CouponData();
        }
        if (current == null) {
            current = new StoreOperationalStatisticsVo.CouponData();
        }
        comparison.setGiftToFriendsCount(buildComparisonData(current.getGiftToFriendsCount(), previous.getGiftToFriendsCount()));
        comparison.setGiftToFriendsAmount(buildComparisonData(current.getGiftToFriendsAmount(), previous.getGiftToFriendsAmount()));
        comparison.setGiftToFriendsUsedCount(buildComparisonData(current.getGiftToFriendsUsedCount(), previous.getGiftToFriendsUsedCount()));
        comparison.setGiftToFriendsUsedAmount(buildComparisonData(current.getGiftToFriendsUsedAmount(), previous.getGiftToFriendsUsedAmount()));
        comparison.setGiftToFriendsUsedAmountRatio(buildComparisonData(current.getGiftToFriendsUsedAmountRatio(), previous.getGiftToFriendsUsedAmountRatio()));
        comparison.setFriendsGiftCount(buildComparisonData(current.getFriendsGiftCount(), previous.getFriendsGiftCount()));
        comparison.setFriendsGiftAmount(buildComparisonData(current.getFriendsGiftAmount(), previous.getFriendsGiftAmount()));
        comparison.setFriendsGiftUsedCount(buildComparisonData(current.getFriendsGiftUsedCount(), previous.getFriendsGiftUsedCount()));
        comparison.setFriendsGiftUsedAmount(buildComparisonData(current.getFriendsGiftUsedAmount(), previous.getFriendsGiftUsedAmount()));
        comparison.setFriendsGiftUsedAmountRatio(buildComparisonData(current.getFriendsGiftUsedAmountRatio(), previous.getFriendsGiftUsedAmountRatio()));
        return comparison;
    }

    /**
     * 构建代金券数据对比
     */
    private StoreOperationalStatisticsComparisonVo.VoucherDataComparison buildVoucherDataComparison(
            StoreOperationalStatisticsVo.VoucherData current, StoreOperationalStatisticsVo.VoucherData previous) {
        StoreOperationalStatisticsComparisonVo.VoucherDataComparison comparison = new StoreOperationalStatisticsComparisonVo.VoucherDataComparison();
        // 如果 previous 为 null，创建空对象避免 NullPointerException
        if (previous == null) {
            previous = new StoreOperationalStatisticsVo.VoucherData();
        }
        if (current == null) {
            current = new StoreOperationalStatisticsVo.VoucherData();
        }
        comparison.setGiftToFriendsCount(buildComparisonData(current.getGiftToFriendsCount(), previous.getGiftToFriendsCount()));
        comparison.setGiftToFriendsAmount(buildComparisonData(current.getGiftToFriendsAmount(), previous.getGiftToFriendsAmount()));
        comparison.setGiftToFriendsUsedCount(buildComparisonData(current.getGiftToFriendsUsedCount(), previous.getGiftToFriendsUsedCount()));
        comparison.setGiftToFriendsUsedAmount(buildComparisonData(current.getGiftToFriendsUsedAmount(), previous.getGiftToFriendsUsedAmount()));
        comparison.setGiftToFriendsUsedAmountRatio(buildComparisonData(current.getGiftToFriendsUsedAmountRatio(), previous.getGiftToFriendsUsedAmountRatio()));
        comparison.setFriendsGiftCount(buildComparisonData(current.getFriendsGiftCount(), previous.getFriendsGiftCount()));
        comparison.setFriendsGiftAmount(buildComparisonData(current.getFriendsGiftAmount(), previous.getFriendsGiftAmount()));
        comparison.setFriendsGiftUsedCount(buildComparisonData(current.getFriendsGiftUsedCount(), previous.getFriendsGiftUsedCount()));
        comparison.setFriendsGiftUsedAmount(buildComparisonData(current.getFriendsGiftUsedAmount(), previous.getFriendsGiftUsedAmount()));
        comparison.setFriendsGiftUsedAmountRatio(buildComparisonData(current.getFriendsGiftUsedAmountRatio(), previous.getFriendsGiftUsedAmountRatio()));
        return comparison;
    }

    /**
     * 构建服务质量数据对比
     */
    private StoreOperationalStatisticsComparisonVo.ServiceQualityDataComparison buildServiceQualityDataComparison(
            StoreOperationalStatisticsVo.ServiceQualityData current, StoreOperationalStatisticsVo.ServiceQualityData previous) {
        StoreOperationalStatisticsComparisonVo.ServiceQualityDataComparison comparison = new StoreOperationalStatisticsComparisonVo.ServiceQualityDataComparison();
        // 如果 previous 为 null，创建空对象避免 NullPointerException
        if (previous == null) {
            previous = new StoreOperationalStatisticsVo.ServiceQualityData();
        }
        if (current == null) {
            current = new StoreOperationalStatisticsVo.ServiceQualityData();
        }
        comparison.setStoreRating(buildComparisonData(current.getStoreRating(), previous.getStoreRating()));
        comparison.setScoreOne(buildComparisonData(current.getScoreOne(), previous.getScoreOne()));
        comparison.setScoreTwo(buildComparisonData(current.getScoreTwo(), previous.getScoreTwo()));
        comparison.setScoreThree(buildComparisonData(current.getScoreThree(), previous.getScoreThree()));
        comparison.setTotalReviews(buildComparisonData(current.getTotalReviews(), previous.getTotalReviews()));
        comparison.setPositiveReviews(buildComparisonData(current.getPositiveReviews(), previous.getPositiveReviews()));
        comparison.setNeutralReviews(buildComparisonData(current.getNeutralReviews(), previous.getNeutralReviews()));
        comparison.setNegativeReviews(buildComparisonData(current.getNegativeReviews(), previous.getNegativeReviews()));
        comparison.setNegativeReviewRatio(buildComparisonData(current.getNegativeReviewRatio(), previous.getNegativeReviewRatio()));
        comparison.setNegativeReviewAppealsCount(buildComparisonData(current.getNegativeReviewAppealsCount(), previous.getNegativeReviewAppealsCount()));
        comparison.setNegativeReviewAppealsSuccessCount(buildComparisonData(current.getNegativeReviewAppealsSuccessCount(), previous.getNegativeReviewAppealsSuccessCount()));
        comparison.setNegativeReviewAppealsSuccessRatio(buildComparisonData(current.getNegativeReviewAppealsSuccessRatio(), previous.getNegativeReviewAppealsSuccessRatio()));
        return comparison;
    }

    /**
     * 构建价目表排名数据对比
     */
    private List<StoreOperationalStatisticsComparisonVo.PriceListRankingComparison> buildPriceListRankingComparison(
            List<StoreOperationalStatisticsVo.PriceListRanking> current, List<StoreOperationalStatisticsVo.PriceListRanking> previous, Integer storeId) {
        List<StoreOperationalStatisticsComparisonVo.PriceListRankingComparison> result = new ArrayList<>();
        
        // 如果当期数据为空，返回空列表
        if (current == null || current.isEmpty()) {
            return result;
        }
        
        // 如果上期数据为空，创建空列表
        if (previous == null) {
            previous = new ArrayList<>();
        }
        
        // 创建上期数据的Map，以priceId为key，方便查找
        Map<Integer, StoreOperationalStatisticsVo.PriceListRanking> previousMap = new HashMap<>();
        for (StoreOperationalStatisticsVo.PriceListRanking prev : previous) {
            if (prev.getPriceId() != null) {
                previousMap.put(prev.getPriceId(), prev);
            }
        }
        
        // 收集需要查询名称的priceId（如果名称为空）
        List<Integer> needQueryPriceIds = new ArrayList<>();
        for (StoreOperationalStatisticsVo.PriceListRanking curr : current) {
            if (curr.getPriceId() != null && 
                (curr.getPriceListItemName() == null || curr.getPriceListItemName().trim().isEmpty())) {
                needQueryPriceIds.add(curr.getPriceId());
            }
        }
        
        // 批量查询价目表名称（根据business_section判断查询美食价目表还是通用价目表）
        Map<Integer, String> priceNameMap = new HashMap<>();
        if (!needQueryPriceIds.isEmpty() && storeId != null) {
            // 查询店铺信息，获取business_section
            StoreInfo storeInfo = storeInfoMapper.selectById(storeId);
            if (storeInfo != null && storeInfo.getBusinessSection() != null && storeInfo.getBusinessSection() == 1) {
                // business_section = 1 表示美食，查询美食价目表
                LambdaQueryWrapper<StoreCuisine> cuisineWrapper = new LambdaQueryWrapper<>();
                cuisineWrapper.in(StoreCuisine::getId, needQueryPriceIds)
                            .eq(StoreCuisine::getStoreId, storeId)
                            .eq(StoreCuisine::getDeleteFlag, 0);
                List<StoreCuisine> cuisines = storeCuisineMapper.selectList(cuisineWrapper);
                for (StoreCuisine cuisine : cuisines) {
                    if (cuisine.getId() != null && cuisine.getName() != null) {
                        priceNameMap.put(cuisine.getId(), cuisine.getName());
                    }
                }
            } else {
                // 其他情况查询通用价目表
                LambdaQueryWrapper<StorePrice> priceWrapper = new LambdaQueryWrapper<>();
                priceWrapper.in(StorePrice::getId, needQueryPriceIds)
                            .eq(StorePrice::getStoreId, storeId)
                            .eq(StorePrice::getDeleteFlag, 0);
                List<StorePrice> prices = storePriceMapper.selectList(priceWrapper);
                for (StorePrice price : prices) {
                    if (price.getId() != null && price.getName() != null) {
                        priceNameMap.put(price.getId(), price.getName());
                    }
                }
            }
        }
        
        // 遍历当期数据，构建对比
        for (StoreOperationalStatisticsVo.PriceListRanking curr : current) {
            StoreOperationalStatisticsComparisonVo.PriceListRankingComparison comparison = 
                new StoreOperationalStatisticsComparisonVo.PriceListRankingComparison();
            
            comparison.setPriceId(curr.getPriceId());
            
            // 设置价目表名称，如果为空则从查询结果中获取（与 convert 一致：有 storeId 时不展示无有效名称的条目）
            String priceListItemName = curr.getPriceListItemName();
            if (priceListItemName == null || priceListItemName.trim().isEmpty()) {
                priceListItemName = priceNameMap.get(curr.getPriceId());
            }
            if (storeId != null && (priceListItemName == null || priceListItemName.trim().isEmpty())) {
                continue;
            }
            comparison.setPriceListItemName(priceListItemName != null ? priceListItemName.trim() : null);
            
            // 获取上期对应的价目表数据
            StoreOperationalStatisticsVo.PriceListRanking prev = previousMap.get(curr.getPriceId());
            
            // 构建浏览量对比
            Long currentPageViews = curr.getPageViews() != null ? curr.getPageViews() : 0L;
            Long previousPageViews = (prev != null && prev.getPageViews() != null) ? prev.getPageViews() : 0L;
            comparison.setPageViews(buildComparisonData(currentPageViews, previousPageViews));
            
            // 构建访客数对比
            Long currentVisitors = curr.getVisitors() != null ? curr.getVisitors() : 0L;
            Long previousVisitors = (prev != null && prev.getVisitors() != null) ? prev.getVisitors() : 0L;
            comparison.setVisitors(buildComparisonData(currentVisitors, previousVisitors));
            
            // 构建分享数对比
            Long currentShares = curr.getShares() != null ? curr.getShares() : 0L;
            Long previousShares = (prev != null && prev.getShares() != null) ? prev.getShares() : 0L;
            comparison.setShares(buildComparisonData(currentShares, previousShares));
            
            result.add(comparison);
        }
        
        return result;
    }

    /**
     * 判断 comparison 中是否至少有一项对比数据有效（current 或 previous 非 0 且非空）。
     */
    private boolean hasComparisonData(StoreOperationalStatisticsComparisonVo comparison) {
        if (comparison == null) {
            return false;
        }
        boolean hasData = hasAnyMeaningfulData(comparison.getTrafficData())
                || hasAnyMeaningfulData(comparison.getInteractionData())
                || hasAnyMeaningfulData(comparison.getCouponData())
                || hasAnyMeaningfulData(comparison.getVoucherData())
                || hasAnyMeaningfulData(comparison.getServiceQualityData());
        if (!hasData && comparison.getPriceListRanking() != null) {
            for (StoreOperationalStatisticsComparisonVo.PriceListRankingComparison pr : comparison.getPriceListRanking()) {
                if (pr != null && (hasMeaningfulValue(pr.getPageViews()) || hasMeaningfulValue(pr.getVisitors()) || hasMeaningfulValue(pr.getShares()))) {
                    hasData = true;
                    break;
                }
            }
        }
        return hasData;
    }

    /**
     * 校验 comparison 中是否至少有一项对比数据有效（current 或 previous 非 0 且非空）。
     * 若所有对比数据的 current 和 previous 都为 0 或空，则抛出 IllegalArgumentException("暂无对比数据")。
     */
    private void validateComparisonHasData(StoreOperationalStatisticsComparisonVo comparison) {
        if (!hasComparisonData(comparison)) {
            throw new IllegalArgumentException("暂无对比数据");
        }
    }

    private boolean hasAnyMeaningfulData(Object dataComparison) {
        if (dataComparison == null) {
            return false;
        }
        java.lang.reflect.Field[] fields = dataComparison.getClass().getDeclaredFields();
        for (java.lang.reflect.Field f : fields) {
            if (StoreOperationalStatisticsComparisonVo.BaseComparisonData.class.isAssignableFrom(f.getType())) {
                try {
                    f.setAccessible(true);
                    StoreOperationalStatisticsComparisonVo.BaseComparisonData b = (StoreOperationalStatisticsComparisonVo.BaseComparisonData) f.get(dataComparison);
                    if (hasMeaningfulValue(b)) {
                        return true;
                    }
                } catch (Exception ignored) {
                }
            }
        }
        return false;
    }

    private boolean hasMeaningfulValue(StoreOperationalStatisticsComparisonVo.BaseComparisonData b) {
        if (b == null) {
            return false;
        }
        return !isNullOrZero(b.getCurrent()) || !isNullOrZero(b.getPrevious());
    }

    private boolean isNullOrZero(Object v) {
        if (v == null) {
            return true;
        }
        if (v instanceof Number) {
            return ((Number) v).doubleValue() == 0;
        }
        if (v instanceof CharSequence) {
            String s = v.toString().trim();
            return s.isEmpty() || "0".equals(s) || "0.0".equals(s);
        }
        return false;
    }

    /**
     * 构建对比数据
     */
    private StoreOperationalStatisticsComparisonVo.BaseComparisonData buildComparisonData(Object current, Object previous) {
        StoreOperationalStatisticsComparisonVo.BaseComparisonData comparisonData = new StoreOperationalStatisticsComparisonVo.BaseComparisonData();
        comparisonData.setCurrent(current);
        comparisonData.setPrevious(previous);

        // 计算变化率
        BigDecimal changeRate = calculateChangeRate(current, previous);
        comparisonData.setChangeRate(changeRate);

        return comparisonData;
    }

    /**
     * 计算变化率（百分比）
     */
    private BigDecimal calculateChangeRate(Object current, Object previous) {
        BigDecimal currentValue = toBigDecimal(current);
        BigDecimal previousValue = toBigDecimal(previous);

        if (previousValue == null || previousValue.compareTo(BigDecimal.ZERO) == 0) {
            if (currentValue != null && currentValue.compareTo(BigDecimal.ZERO) > 0) {
                return BigDecimal.valueOf(100); // 从0增长，视为100%增长
            }
            return BigDecimal.ZERO;
        }

        if (currentValue == null) {
            currentValue = BigDecimal.ZERO;
        }

        // 变化率 = ((当期 - 上期) / 上期) * 100
        BigDecimal change = currentValue.subtract(previousValue);
        BigDecimal rate = change.divide(previousValue, 4, RoundingMode.HALF_UP)
                .multiply(BigDecimal.valueOf(100));
        return rate.setScale(2, RoundingMode.HALF_UP);
    }

    /**
     * 将对象转换为BigDecimal
     */
    private BigDecimal toBigDecimal(Object value) {
        if (value == null) {
            return BigDecimal.ZERO;
        }
        if (value instanceof BigDecimal) {
            return (BigDecimal) value;
        }
        if (value instanceof Number) {
            return BigDecimal.valueOf(((Number) value).doubleValue());
        }
        try {
            return new BigDecimal(value.toString());
        } catch (Exception e) {
            return BigDecimal.ZERO;
        }
    }

    @Override
    public StoreOperationalStatisticsVo getStatisticsInTrackFormat(Integer storeId, String startTime, String endTime) {
        log.info("StoreOperationalStatisticsServiceImpl.getStatisticsInTrackFormat - storeId={}, startTime={}, endTime={}", 
                storeId, startTime, endTime);
        
        // 计算统计数据
        StoreOperationalStatisticsVo statistics = calculateStatistics(storeId, startTime, endTime);
        
        // 不再保存统计数据到历史表，只有对比接口才会保存历史数据
        
        return statistics;
    }
    
    /**
     * 保存对比统计数据到历史表
     * @param storeId 店铺ID
     * @param currentStartTime 当期开始时间
     * @param currentEndTime 当期结束时间
     * @param previousStartTime 上期开始时间
     * @param previousEndTime 上期结束时间
     * @param comparison 对比数据
     * @param pdfUrl PDF文件URL（可选）
     * @return 历史记录ID，保存失败返回null
     */
    private Integer saveStatisticsHistory(Integer storeId, String currentStartTime, String currentEndTime,
                                          String previousStartTime, String previousEndTime,
                                          StoreOperationalStatisticsComparisonVo comparison, String pdfUrl) {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
            Date startDate = sdf.parse(currentStartTime);
            Date endDate = sdf.parse(currentEndTime);
            Date previousStartDate = sdf.parse(previousStartTime);
            Date previousEndDate = sdf.parse(previousEndTime);

            StoreOperationalStatisticsHistory history = new StoreOperationalStatisticsHistory();
            history.setStoreId(storeId);
            history.setStartTime(startDate);
            history.setEndTime(endDate);
            history.setPreviousStartTime(previousStartDate);
            history.setPreviousEndTime(previousEndDate);
            history.setQueryTime(new Date());
            
            // 将对比统计数据序列化为JSON字符串（包含当期、上期和变化率等完整对比数据）
            String statisticsJson = JSON.toJSONString(comparison);
            history.setStatisticsData(statisticsJson);
            
            // 如果提供了PDF URL，则保存
            if (pdfUrl != null && !pdfUrl.trim().isEmpty()) {
                history.setPdfUrl(pdfUrl);
            }

            statisticsHistoryMapper.insert(history);
            log.info("保存对比统计数据到历史表成功 - storeId={}, currentStartTime={}, currentEndTime={}, previousStartTime={}, previousEndTime={}, historyId={}", 
                    storeId, currentStartTime, currentEndTime, previousStartTime, previousEndTime, history.getId());
            return history.getId();
        } catch (Exception e) {
            log.error("保存对比统计数据到历史表失败 - storeId={}, currentStartTime={}, currentEndTime={}, previousStartTime={}, previousEndTime={}, error={}", 
                    storeId, currentStartTime, currentEndTime, previousStartTime, previousEndTime, e.getMessage(), e);
            // 保存失败不影响主流程，只记录日志
            return null;
        }
    }

    @Override
    public IPage<StoreOperationalStatisticsHistory> getHistoryList(Integer storeId, Integer page, Integer size, String createdTime) {
        log.info("StoreOperationalStatisticsServiceImpl.getHistoryList - storeId={}, page={}, size={}, createdTime={}", storeId, page, size, createdTime);
        
        // 参数校验
        if (storeId == null || storeId <= 0) {
            throw new IllegalArgumentException("店铺ID不能为空且必须大于0");
        }
        int pageNum = page != null && page > 0 ? page : 1;
        int pageSize = size != null && size > 0 ? size : 10;
        
        // 构建分页对象
        IPage<StoreOperationalStatisticsHistory> pageObj = new Page<>(pageNum, pageSize);
        
        // 构建查询条件
        LambdaQueryWrapper<StoreOperationalStatisticsHistory> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StoreOperationalStatisticsHistory::getStoreId, storeId)
               .eq(StoreOperationalStatisticsHistory::getDeleteFlag, 0)
               .orderByDesc(StoreOperationalStatisticsHistory::getQueryTime);
        
        // created_time 可选：与 query_time 为同一天（query_time 格式 yyyy-MM-dd HH:mm:ss，created_time 格式 yyyy-MM-dd）
        if (StringUtils.hasText(createdTime)) {
            wrapper.apply("DATE(query_time) = {0}", createdTime.trim());
        }
        
        // 执行分页查询
        IPage<StoreOperationalStatisticsHistory> result = statisticsHistoryMapper.selectPage(pageObj, wrapper);
        
        log.info("查询历史统计记录列表成功 - storeId={}, 共{}条记录，当前页{}条", storeId, result.getTotal(), result.getRecords().size());
        return result;
    }

    @Override
    public StoreOperationalStatisticsHistory getHistoryById(Integer id) {
        log.info("StoreOperationalStatisticsServiceImpl.getHistoryById - id={}", id);
        
        // 参数校验
        if (id == null || id <= 0) {
            throw new IllegalArgumentException("历史记录ID不能为空且必须大于0");
        }
        
        // 查询历史记录
        LambdaQueryWrapper<StoreOperationalStatisticsHistory> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StoreOperationalStatisticsHistory::getId, id)
               .eq(StoreOperationalStatisticsHistory::getDeleteFlag, 0);
        
        StoreOperationalStatisticsHistory history = statisticsHistoryMapper.selectOne(wrapper);
        
        if (history == null) {
            log.warn("查询历史统计记录详情失败，记录不存在或已删除 - id={}", id);
            throw new RuntimeException("历史记录不存在或已删除");
        }
        
        log.info("查询历史统计记录详情成功 - id={}", id);
        return history;
    }

    @Override
    public boolean deleteHistory(Integer id) {
        log.info("StoreOperationalStatisticsServiceImpl.deleteHistory - id={}", id);
        
        try {
            // 使用逻辑删除
            LambdaUpdateWrapper<StoreOperationalStatisticsHistory> wrapper = new LambdaUpdateWrapper<>();
            wrapper.eq(StoreOperationalStatisticsHistory::getId, id)
                   .eq(StoreOperationalStatisticsHistory::getDeleteFlag, 0)
                   .set(StoreOperationalStatisticsHistory::getDeleteFlag, 1);
            
            int result = statisticsHistoryMapper.update(null, wrapper);
            return result > 0;
        } catch (Exception e) {
            log.error("删除历史统计记录失败 - id={}, error={}", id, e.getMessage(), e);
            return false;
        }
    }

    @Override
    public boolean batchDeleteHistory(List<Integer> ids) {
        log.info("StoreOperationalStatisticsServiceImpl.batchDeleteHistory - ids={}", ids);
        
        if (ids == null || ids.isEmpty()) {
            log.warn("批量删除历史统计记录失败，ID列表为空");
            return false;
        }
        
        try {
            // 使用逻辑删除
            LambdaUpdateWrapper<StoreOperationalStatisticsHistory> wrapper = new LambdaUpdateWrapper<>();
            wrapper.in(StoreOperationalStatisticsHistory::getId, ids)
                   .eq(StoreOperationalStatisticsHistory::getDeleteFlag, 0)
                   .set(StoreOperationalStatisticsHistory::getDeleteFlag, 1);
            
            int result = statisticsHistoryMapper.update(null, wrapper);
            return result > 0;
        } catch (Exception e) {
            log.error("批量删除历史统计记录失败 - ids={}, error={}", ids, e.getMessage(), e);
            return false;
        }
    }

    @Override
    public boolean updateHistoryPdfUrl(Integer historyId, String pdfUrl) {
        log.info("StoreOperationalStatisticsServiceImpl.updateHistoryPdfUrl - historyId={}, pdfUrl={}", historyId, pdfUrl);
        
        if (historyId == null || historyId <= 0) {
            log.warn("更新历史统计记录PDF URL失败，历史记录ID无效 - historyId={}", historyId);
            return false;
        }
        
        if (pdfUrl == null || pdfUrl.trim().isEmpty()) {
            log.warn("更新历史统计记录PDF URL失败，PDF URL为空 - historyId={}", historyId);
            return false;
        }
        
        try {
            // 查询历史记录是否存在且未删除
            StoreOperationalStatisticsHistory history = statisticsHistoryMapper.selectOne(
                    new LambdaQueryWrapper<StoreOperationalStatisticsHistory>()
                            .eq(StoreOperationalStatisticsHistory::getId, historyId)
                            .eq(StoreOperationalStatisticsHistory::getDeleteFlag, 0));
            
            if (history == null) {
                log.warn("更新历史统计记录PDF URL失败，历史记录不存在或已删除 - historyId={}", historyId);
                return false;
            }
            
            // 更新PDF URL
            LambdaUpdateWrapper<StoreOperationalStatisticsHistory> wrapper = new LambdaUpdateWrapper<>();
            wrapper.eq(StoreOperationalStatisticsHistory::getId, historyId)
                   .eq(StoreOperationalStatisticsHistory::getDeleteFlag, 0)
                   .set(StoreOperationalStatisticsHistory::getPdfUrl, pdfUrl.trim());
            
            int result = statisticsHistoryMapper.update(null, wrapper);
            if (result > 0) {
                log.info("更新历史统计记录PDF URL成功 - historyId={}, pdfUrl={}", historyId, pdfUrl);
                return true;
            } else {
                log.warn("更新历史统计记录PDF URL失败，未更新任何记录 - historyId={}", historyId);
                return false;
            }
        } catch (Exception e) {
            log.error("更新历史统计记录PDF URL失败 - historyId={}, pdfUrl={}, error={}", historyId, pdfUrl, e.getMessage(), e);
            return false;
        }
    }

    @Override
    public boolean updateHistoryAiAnalysis(Integer historyId, Integer aiAnalysisCompleted, String summary, String optimizationSuggestions) {
        log.info("StoreOperationalStatisticsServiceImpl.updateHistoryAiAnalysis - historyId={}, aiAnalysisCompleted={}", historyId, aiAnalysisCompleted);
        
        if (historyId == null || historyId <= 0) {
            log.warn("更新历史统计记录AI分析结果失败，历史记录ID无效 - historyId={}", historyId);
            return false;
        }
        
        try {
            // 查询历史记录是否存在且未删除
            StoreOperationalStatisticsHistory history = statisticsHistoryMapper.selectOne(
                    new LambdaQueryWrapper<StoreOperationalStatisticsHistory>()
                            .eq(StoreOperationalStatisticsHistory::getId, historyId)
                            .eq(StoreOperationalStatisticsHistory::getDeleteFlag, 0));
            
            if (history == null) {
                log.warn("更新历史统计记录AI分析结果失败，历史记录不存在或已删除 - historyId={}", historyId);
                return false;
            }
            
            // 更新AI分析相关字段
            LambdaUpdateWrapper<StoreOperationalStatisticsHistory> wrapper = new LambdaUpdateWrapper<>();
            wrapper.eq(StoreOperationalStatisticsHistory::getId, historyId)
                   .eq(StoreOperationalStatisticsHistory::getDeleteFlag, 0);
            
            if (aiAnalysisCompleted != null) {
                wrapper.set(StoreOperationalStatisticsHistory::getAiAnalysisCompleted, aiAnalysisCompleted);
            }
            if (summary != null) {
                wrapper.set(StoreOperationalStatisticsHistory::getSummary, summary.trim());
            }
            if (optimizationSuggestions != null) {
                wrapper.set(StoreOperationalStatisticsHistory::getOptimizationSuggestions, optimizationSuggestions.trim());
            }
            
            int result = statisticsHistoryMapper.update(null, wrapper);
            if (result > 0) {
                log.info("更新历史统计记录AI分析结果成功 - historyId={}, aiAnalysisCompleted={}", historyId, aiAnalysisCompleted);
                return true;
            } else {
                log.warn("更新历史统计记录AI分析结果失败，未更新任何记录 - historyId={}", historyId);
                return false;
            }
        } catch (Exception e) {
            log.error("更新历史统计记录AI分析结果失败 - historyId={}, error={}", historyId, e.getMessage(), e);
            return false;
        }
    }
    
    // ==================== 累加和转换方法 ====================
    
    /**
     * 累加流量数据
     */
    @SuppressWarnings("unchecked")
    private void aggregateTrafficData(String trafficDataJson, Map<String, Long> accumulator) {
        try {
            Map<String, Object> data = (Map<String, Object>) JSON.parseObject(trafficDataJson, Map.class);
            if (data == null) return;
            
            // 累加各个字段
            accumulator.put("searchCount", accumulator.getOrDefault("searchCount", 0L) + 
                    getLongValue(data, "searchCount"));
            accumulator.put("viewCount", accumulator.getOrDefault("viewCount", 0L) + 
                    getLongValue(data, "viewCount"));
            accumulator.put("visitorCount", accumulator.getOrDefault("visitorCount", 0L) + 
                    getLongValue(data, "visitorCount"));
            accumulator.put("newVisitorCount", accumulator.getOrDefault("newVisitorCount", 0L) + 
                    getLongValue(data, "newVisitorCount"));
            accumulator.put("totalDuration", accumulator.getOrDefault("totalDuration", 0L) + 
                    getLongValue(data, "totalDuration"));
            accumulator.put("avgDuration", accumulator.getOrDefault("avgDuration", 0L) + 
                    getLongValue(data, "avgDuration"));
        } catch (Exception e) {
            log.warn("解析流量数据失败: {}", trafficDataJson, e);
        }
    }
    
    /**
     * 累加互动数据
     */
    @SuppressWarnings("unchecked")
    private void aggregateInteractionData(String interactionDataJson, Map<String, Long> accumulator) {
        try {
            Map<String, Object> data = (Map<String, Object>) JSON.parseObject(interactionDataJson, Map.class);
            if (data == null) return;
            
            accumulator.put("collectCount", accumulator.getOrDefault("collectCount", 0L) + 
                    getLongValue(data, "collectCount"));
            accumulator.put("shareCount", accumulator.getOrDefault("shareCount", 0L) + 
                    getLongValue(data, "shareCount"));
            accumulator.put("checkinCount", accumulator.getOrDefault("checkinCount", 0L) + 
                    getLongValue(data, "checkinCount"));
            accumulator.put("consultCount", accumulator.getOrDefault("consultCount", 0L) + 
                    getLongValue(data, "consultCount"));
            accumulator.put("friendCount", accumulator.getOrDefault("friendCount", 0L) + 
                    getLongValue(data, "friendCount"));
            accumulator.put("followCount", accumulator.getOrDefault("followCount", 0L) + 
                    getLongValue(data, "followCount"));
            accumulator.put("fansCount", accumulator.getOrDefault("fansCount", 0L) + 
                    getLongValue(data, "fansCount"));
            accumulator.put("postCount", accumulator.getOrDefault("postCount", 0L) + 
                    getLongValue(data, "postCount"));
            accumulator.put("postLikeCount", accumulator.getOrDefault("postLikeCount", 0L) + 
                    getLongValue(data, "postLikeCount"));
            accumulator.put("postCommentCount", accumulator.getOrDefault("postCommentCount", 0L) + 
                    getLongValue(data, "postCommentCount"));
            accumulator.put("postRepostCount", accumulator.getOrDefault("postRepostCount", 0L) + 
                    getLongValue(data, "postRepostCount"));
            accumulator.put("reportCount", accumulator.getOrDefault("reportCount", 0L) + 
                    getLongValue(data, "reportCount"));
            accumulator.put("blockCount", accumulator.getOrDefault("blockCount", 0L) + 
                    getLongValue(data, "blockCount"));
        } catch (Exception e) {
            log.warn("解析互动数据失败: {}", interactionDataJson, e);
        }
    }
    
    /**
     * 累加优惠券数据
     */
    @SuppressWarnings("unchecked")
    private void aggregateCouponData(String couponDataJson, Map<String, Object> accumulator) {
        try {
            Map<String, Object> data = (Map<String, Object>) JSON.parseObject(couponDataJson, Map.class);
            if (data == null) return;
            
            // 累加Long类型字段
            accumulator.put("giveToFriendCount", getLongValue(accumulator, "giveToFriendCount") + 
                    getLongValue(data, "giveToFriendCount"));
            accumulator.put("giveToFriendUseCount", getLongValue(accumulator, "giveToFriendUseCount") + 
                    getLongValue(data, "giveToFriendUseCount"));
            accumulator.put("friendGiveCount", getLongValue(accumulator, "friendGiveCount") + 
                    getLongValue(data, "friendGiveCount"));
            accumulator.put("friendGiveUseCount", getLongValue(accumulator, "friendGiveUseCount") + 
                    getLongValue(data, "friendGiveUseCount"));
            
            // 累加BigDecimal类型字段
            accumulator.put("giveToFriendAmount", getBigDecimalValue(accumulator, "giveToFriendAmount")
                    .add(getBigDecimalValue(data, "giveToFriendAmount")));
            accumulator.put("giveToFriendUseAmount", getBigDecimalValue(accumulator, "giveToFriendUseAmount")
                    .add(getBigDecimalValue(data, "giveToFriendUseAmount")));
            accumulator.put("friendGiveAmount", getBigDecimalValue(accumulator, "friendGiveAmount")
                    .add(getBigDecimalValue(data, "friendGiveAmount")));
            accumulator.put("friendGiveUseAmount", getBigDecimalValue(accumulator, "friendGiveUseAmount")
                    .add(getBigDecimalValue(data, "friendGiveUseAmount")));
        } catch (Exception e) {
            log.warn("解析优惠券数据失败: {}", couponDataJson, e);
        }
    }
    
    /**
     * 累加代金券数据
     */
    @SuppressWarnings("unchecked")
    private void aggregateVoucherData(String voucherDataJson, Map<String, Object> accumulator) {
        try {
            Map<String, Object> data = (Map<String, Object>) JSON.parseObject(voucherDataJson, Map.class);
            if (data == null) return;
            
            // 累加Long类型字段
            accumulator.put("giveToFriendCount", getLongValue(accumulator, "giveToFriendCount") + 
                    getLongValue(data, "giveToFriendCount"));
            accumulator.put("giveToFriendUseCount", getLongValue(accumulator, "giveToFriendUseCount") + 
                    getLongValue(data, "giveToFriendUseCount"));
            accumulator.put("friendGiveCount", getLongValue(accumulator, "friendGiveCount") + 
                    getLongValue(data, "friendGiveCount"));
            accumulator.put("friendGiveUseCount", getLongValue(accumulator, "friendGiveUseCount") + 
                    getLongValue(data, "friendGiveUseCount"));
            
            // 累加BigDecimal类型字段
            accumulator.put("giveToFriendAmount", getBigDecimalValue(accumulator, "giveToFriendAmount")
                    .add(getBigDecimalValue(data, "giveToFriendAmount")));
            accumulator.put("giveToFriendUseAmount", getBigDecimalValue(accumulator, "giveToFriendUseAmount")
                    .add(getBigDecimalValue(data, "giveToFriendUseAmount")));
            accumulator.put("friendGiveAmount", getBigDecimalValue(accumulator, "friendGiveAmount")
                    .add(getBigDecimalValue(data, "friendGiveAmount")));
            accumulator.put("friendGiveUseAmount", getBigDecimalValue(accumulator, "friendGiveUseAmount")
                    .add(getBigDecimalValue(data, "friendGiveUseAmount")));
        } catch (Exception e) {
            log.warn("解析代金券数据失败: {}", voucherDataJson, e);
        }
    }
    
    /**
     * 累加服务质量数据
     */
    @SuppressWarnings("unchecked")
    private void aggregateServiceData(String serviceDataJson, Map<String, Object> accumulator) {
        try {
            Map<String, Object> data = (Map<String, Object>) JSON.parseObject(serviceDataJson, Map.class);
            if (data == null) return;
            
            // 累加评分（需要计算平均值）
            accumulator.put("storeScoreSum", getBigDecimalValue(accumulator, "storeScoreSum")
                    .add(getBigDecimalValue(data, "storeScore")));
            accumulator.put("scoreOneSum", getBigDecimalValue(accumulator, "scoreOneSum")
                    .add(getBigDecimalValue(data, "scoreOne")));
            accumulator.put("scoreTwoSum", getBigDecimalValue(accumulator, "scoreTwoSum")
                    .add(getBigDecimalValue(data, "scoreTwo")));
            accumulator.put("scoreThreeSum", getBigDecimalValue(accumulator, "scoreThreeSum")
                    .add(getBigDecimalValue(data, "scoreThree")));
            
            // 累加Long类型字段
            accumulator.put("ratingCount", getLongValue(accumulator, "ratingCount") + 
                    getLongValue(data, "ratingCount"));
            accumulator.put("goodRatingCount", getLongValue(accumulator, "goodRatingCount") + 
                    getLongValue(data, "goodRatingCount"));
            accumulator.put("midRatingCount", getLongValue(accumulator, "midRatingCount") + 
                    getLongValue(data, "midRatingCount"));
            accumulator.put("badRatingCount", getLongValue(accumulator, "badRatingCount") + 
                    getLongValue(data, "badRatingCount"));
            accumulator.put("appealCount", getLongValue(accumulator, "appealCount") + 
                    getLongValue(data, "appealCount"));
            accumulator.put("appealSuccessCount", getLongValue(accumulator, "appealSuccessCount") + 
                    getLongValue(data, "appealSuccessCount"));
        } catch (Exception e) {
            log.warn("解析服务质量数据失败: {}", serviceDataJson, e);
        }
    }
    
    /**
     * 累加价目表排名数据
     */
    @SuppressWarnings("unchecked")
    private void aggregatePriceRankingData(String priceRankingDataJson, Map<Integer, Map<String, Long>> accumulator) {
        try {
            List<Map<String, Object>> dataList = (List<Map<String, Object>>) (List<?>) JSON.parseArray(priceRankingDataJson);
            if (dataList == null) return;
            
            for (Map<String, Object> item : dataList) {
                Integer priceId = getIntegerValue(item, "priceId");
                if (priceId == null) continue;
                
                Map<String, Long> priceData = accumulator.computeIfAbsent(priceId, k -> new HashMap<>());
                priceData.put("viewCount", priceData.getOrDefault("viewCount", 0L) + 
                        getLongValue(item, "viewCount"));
                priceData.put("visitorCount", priceData.getOrDefault("visitorCount", 0L) + 
                        getLongValue(item, "visitorCount"));
                priceData.put("shareCount", priceData.getOrDefault("shareCount", 0L) + 
                        getLongValue(item, "shareCount"));
            }
        } catch (Exception e) {
            log.warn("解析价目表排名数据失败: {}", priceRankingDataJson, e);
        }
    }
    
    /**
     * 转换为流量数据VO
     */
    private StoreOperationalStatisticsVo.TrafficData convertToTrafficDataVo(Map<String, Long> accumulator, int count) {
        StoreOperationalStatisticsVo.TrafficData vo = new StoreOperationalStatisticsVo.TrafficData();
        vo.setStoreSearchVolume(accumulator.getOrDefault("searchCount", 0L));
        vo.setPageViews(accumulator.getOrDefault("viewCount", 0L));
        vo.setVisitors(accumulator.getOrDefault("visitorCount", 0L));
        vo.setNewVisitors(accumulator.getOrDefault("newVisitorCount", 0L));
        
        // 访问时长转换为秒（原数据是毫秒）
        Long totalDuration = accumulator.getOrDefault("totalDuration", 0L);
        vo.setVisitDuration(totalDuration > 0 ? totalDuration / 1000 : 0L);
        
        // 平均访问时长：总时长除以访问次数（转换为秒）
        Long visitorCount = accumulator.getOrDefault("visitorCount", 0L);
        if (count > 0 && totalDuration > 0 && visitorCount > 0) {
            // 平均访问时长 = 总时长 / 访客数（转换为秒）
            vo.setAvgVisitDuration((totalDuration / visitorCount) / 1000);
        } else {
            // 如果没有访客数，使用原有的平均时长数据
            Long avgDuration = accumulator.getOrDefault("avgDuration", 0L);
            vo.setAvgVisitDuration(avgDuration > 0 ? avgDuration / 1000 : 0L);
        }
        
        return vo;
    }
    
    /**
     * 转换为互动数据VO
     */
    private StoreOperationalStatisticsVo.InteractionData convertToInteractionDataVo(Map<String, Long> accumulator) {
        StoreOperationalStatisticsVo.InteractionData vo = new StoreOperationalStatisticsVo.InteractionData();
        vo.setStoreCollectionCount(accumulator.getOrDefault("collectCount", 0L));
        vo.setStoreShareCount(accumulator.getOrDefault("shareCount", 0L));
        vo.setStoreCheckInCount(accumulator.getOrDefault("checkinCount", 0L));
        vo.setConsultMerchantCount(accumulator.getOrDefault("consultCount", 0L));
        vo.setFriendsCount(accumulator.getOrDefault("friendCount", 0L));
        vo.setFollowCount(accumulator.getOrDefault("followCount", 0L));
        vo.setFansCount(accumulator.getOrDefault("fansCount", 0L));
        vo.setPostsPublishedCount(accumulator.getOrDefault("postCount", 0L));
        vo.setPostLikesCount(accumulator.getOrDefault("postLikeCount", 0L));
        vo.setPostCommentsCount(accumulator.getOrDefault("postCommentCount", 0L));
        vo.setPostSharesCount(accumulator.getOrDefault("postRepostCount", 0L));
        vo.setReportedCount(accumulator.getOrDefault("reportCount", 0L));
        vo.setBlockedCount(accumulator.getOrDefault("blockCount", 0L));
        return vo;
    }
    
    /**
     * 转换为优惠券数据VO
     */
    private StoreOperationalStatisticsVo.CouponData convertToCouponDataVo(Map<String, Object> accumulator) {
        StoreOperationalStatisticsVo.CouponData vo = new StoreOperationalStatisticsVo.CouponData();
        vo.setGiftToFriendsCount(getLongValue(accumulator, "giveToFriendCount"));
        vo.setGiftToFriendsAmount(getBigDecimalValue(accumulator, "giveToFriendAmount"));
        vo.setGiftToFriendsUsedCount(getLongValue(accumulator, "giveToFriendUseCount"));
        vo.setGiftToFriendsUsedAmount(getBigDecimalValue(accumulator, "giveToFriendUseAmount"));
        
        // 计算使用金额占比
        BigDecimal giftAmount = getBigDecimalValue(accumulator, "giveToFriendAmount");
        BigDecimal giftUsedAmount = getBigDecimalValue(accumulator, "giveToFriendUseAmount");
        if (giftAmount.compareTo(BigDecimal.ZERO) > 0) {
            vo.setGiftToFriendsUsedAmountRatio(giftUsedAmount.divide(giftAmount, 4, RoundingMode.HALF_UP)
                    .multiply(BigDecimal.valueOf(100)).setScale(2, RoundingMode.HALF_UP));
        } else {
            vo.setGiftToFriendsUsedAmountRatio(BigDecimal.ZERO);
        }
        
        vo.setFriendsGiftCount(getLongValue(accumulator, "friendGiveCount"));
        vo.setFriendsGiftAmount(getBigDecimalValue(accumulator, "friendGiveAmount"));
        vo.setFriendsGiftUsedCount(getLongValue(accumulator, "friendGiveUseCount"));
        vo.setFriendsGiftUsedAmount(getBigDecimalValue(accumulator, "friendGiveUseAmount"));
        
        // 计算好友赠送使用金额占比
        BigDecimal friendAmount = getBigDecimalValue(accumulator, "friendGiveAmount");
        BigDecimal friendUsedAmount = getBigDecimalValue(accumulator, "friendGiveUseAmount");
        if (friendAmount.compareTo(BigDecimal.ZERO) > 0) {
            vo.setFriendsGiftUsedAmountRatio(friendUsedAmount.divide(friendAmount, 4, RoundingMode.HALF_UP)
                    .multiply(BigDecimal.valueOf(100)).setScale(2, RoundingMode.HALF_UP));
        } else {
            vo.setFriendsGiftUsedAmountRatio(BigDecimal.ZERO);
        }
        
        return vo;
    }
    
    /**
     * 转换为代金券数据VO
     */
    private StoreOperationalStatisticsVo.VoucherData convertToVoucherDataVo(Map<String, Object> accumulator) {
        StoreOperationalStatisticsVo.VoucherData vo = new StoreOperationalStatisticsVo.VoucherData();
        vo.setGiftToFriendsCount(getLongValue(accumulator, "giveToFriendCount"));
        vo.setGiftToFriendsAmount(getBigDecimalValue(accumulator, "giveToFriendAmount"));
        vo.setGiftToFriendsUsedCount(getLongValue(accumulator, "giveToFriendUseCount"));
        vo.setGiftToFriendsUsedAmount(getBigDecimalValue(accumulator, "giveToFriendUseAmount"));
        
        // 计算使用金额占比
        BigDecimal giftAmount = getBigDecimalValue(accumulator, "giveToFriendAmount");
        BigDecimal giftUsedAmount = getBigDecimalValue(accumulator, "giveToFriendUseAmount");
        if (giftAmount.compareTo(BigDecimal.ZERO) > 0) {
            vo.setGiftToFriendsUsedAmountRatio(giftUsedAmount.divide(giftAmount, 4, RoundingMode.HALF_UP)
                    .multiply(BigDecimal.valueOf(100)).setScale(2, RoundingMode.HALF_UP));
        } else {
            vo.setGiftToFriendsUsedAmountRatio(BigDecimal.ZERO);
        }
        
        vo.setFriendsGiftCount(getLongValue(accumulator, "friendGiveCount"));
        vo.setFriendsGiftAmount(getBigDecimalValue(accumulator, "friendGiveAmount"));
        vo.setFriendsGiftUsedCount(getLongValue(accumulator, "friendGiveUseCount"));
        vo.setFriendsGiftUsedAmount(getBigDecimalValue(accumulator, "friendGiveUseAmount"));
        
        // 计算好友赠送使用金额占比
        BigDecimal friendAmount = getBigDecimalValue(accumulator, "friendGiveAmount");
        BigDecimal friendUsedAmount = getBigDecimalValue(accumulator, "friendGiveUseAmount");
        if (friendAmount.compareTo(BigDecimal.ZERO) > 0) {
            vo.setFriendsGiftUsedAmountRatio(friendUsedAmount.divide(friendAmount, 4, RoundingMode.HALF_UP)
                    .multiply(BigDecimal.valueOf(100)).setScale(2, RoundingMode.HALF_UP));
        } else {
            vo.setFriendsGiftUsedAmountRatio(BigDecimal.ZERO);
        }
        
        return vo;
    }
    
    /**
     * 转换为服务质量数据VO
     */
    private StoreOperationalStatisticsVo.ServiceQualityData convertToServiceQualityDataVo(Map<String, Object> accumulator, int count) {
        StoreOperationalStatisticsVo.ServiceQualityData vo = new StoreOperationalStatisticsVo.ServiceQualityData();
        
        // 计算平均评分
        if (count > 0) {
            BigDecimal storeScoreSum = getBigDecimalValue(accumulator, "storeScoreSum");
            BigDecimal scoreOneSum = getBigDecimalValue(accumulator, "scoreOneSum");
            BigDecimal scoreTwoSum = getBigDecimalValue(accumulator, "scoreTwoSum");
            BigDecimal scoreThreeSum = getBigDecimalValue(accumulator, "scoreThreeSum");
            
            vo.setStoreRating(storeScoreSum.divide(BigDecimal.valueOf(count), 2, RoundingMode.HALF_UP));
            vo.setScoreOne(scoreOneSum.divide(BigDecimal.valueOf(count), 2, RoundingMode.HALF_UP));
            vo.setScoreTwo(scoreTwoSum.divide(BigDecimal.valueOf(count), 2, RoundingMode.HALF_UP));
            vo.setScoreThree(scoreThreeSum.divide(BigDecimal.valueOf(count), 2, RoundingMode.HALF_UP));
        } else {
            vo.setStoreRating(BigDecimal.ZERO);
            vo.setScoreOne(BigDecimal.ZERO);
            vo.setScoreTwo(BigDecimal.ZERO);
            vo.setScoreThree(BigDecimal.ZERO);
        }
        
        vo.setTotalReviews(getLongValue(accumulator, "ratingCount"));
        vo.setPositiveReviews(getLongValue(accumulator, "goodRatingCount"));
        vo.setNeutralReviews(getLongValue(accumulator, "midRatingCount"));
        vo.setNegativeReviews(getLongValue(accumulator, "badRatingCount"));
        
        // 计算差评占比
        Long ratingCount = getLongValue(accumulator, "ratingCount");
        Long badRatingCount = getLongValue(accumulator, "badRatingCount");
        if (ratingCount > 0) {
            vo.setNegativeReviewRatio(BigDecimal.valueOf(badRatingCount)
                    .divide(BigDecimal.valueOf(ratingCount), 4, RoundingMode.HALF_UP)
                    .multiply(BigDecimal.valueOf(100)).setScale(2, RoundingMode.HALF_UP));
        } else {
            vo.setNegativeReviewRatio(BigDecimal.ZERO);
        }
        
        vo.setNegativeReviewAppealsCount(getLongValue(accumulator, "appealCount"));
        vo.setNegativeReviewAppealsSuccessCount(getLongValue(accumulator, "appealSuccessCount"));
        
        // 计算差评申诉成功占比
        Long appealCount = getLongValue(accumulator, "appealCount");
        Long appealSuccessCount = getLongValue(accumulator, "appealSuccessCount");
        if (appealCount > 0) {
            vo.setNegativeReviewAppealsSuccessRatio(BigDecimal.valueOf(appealSuccessCount)
                    .divide(BigDecimal.valueOf(appealCount), 4, RoundingMode.HALF_UP)
                    .multiply(BigDecimal.valueOf(100)).setScale(2, RoundingMode.HALF_UP));
        } else {
            vo.setNegativeReviewAppealsSuccessRatio(BigDecimal.ZERO);
        }
        
        return vo;
    }
    
    /**
     * 转换为价目表排名数据VO
     */
    private List<StoreOperationalStatisticsVo.PriceListRanking> convertToPriceListRankingVo(Map<Integer, Map<String, Long>> accumulator, Integer storeId) {
        List<StoreOperationalStatisticsVo.PriceListRanking> result = new ArrayList<>();
        
        // 如果累加器为空，直接返回
        if (accumulator == null || accumulator.isEmpty()) {
            return result;
        }
        
        // 批量查询价目表名称（根据business_section判断查询美食价目表还是通用价目表）
        List<Integer> priceIds = new ArrayList<>(accumulator.keySet());
        Map<Integer, String> priceNameMap = new HashMap<>();
        if (!priceIds.isEmpty() && storeId != null) {
            // 查询店铺信息，获取business_section
            StoreInfo storeInfo = storeInfoMapper.selectById(storeId);
            if (storeInfo != null && storeInfo.getBusinessSection() != null && storeInfo.getBusinessSection() == 1) {
                // business_section = 1 表示美食，查询美食价目表
                LambdaQueryWrapper<StoreCuisine> cuisineWrapper = new LambdaQueryWrapper<>();
                cuisineWrapper.in(StoreCuisine::getId, priceIds)
                            .eq(StoreCuisine::getStoreId, storeId)
                            .eq(StoreCuisine::getDeleteFlag, 0);
                List<StoreCuisine> cuisines = storeCuisineMapper.selectList(cuisineWrapper);
                for (StoreCuisine cuisine : cuisines) {
                    if (cuisine.getId() != null && cuisine.getName() != null) {
                        priceNameMap.put(cuisine.getId(), cuisine.getName());
                    }
                }
            } else {
                // 其他情况查询通用价目表
                LambdaQueryWrapper<StorePrice> priceWrapper = new LambdaQueryWrapper<>();
                priceWrapper.in(StorePrice::getId, priceIds)
                            .eq(StorePrice::getStoreId, storeId)
                            .eq(StorePrice::getDeleteFlag, 0);
                List<StorePrice> prices = storePriceMapper.selectList(priceWrapper);
                for (StorePrice price : prices) {
                    if (price.getId() != null && price.getName() != null) {
                        priceNameMap.put(price.getId(), price.getName());
                    }
                }
            }
        }
        
        // 转换为列表：有 storeId 时仅保留本店未删除且能解析到名称的价目/菜品
        for (Map.Entry<Integer, Map<String, Long>> entry : accumulator.entrySet()) {
            Integer priceId = entry.getKey();
            if (priceId == null) {
                continue;
            }
            String itemName = priceNameMap.get(priceId);
            if (storeId != null) {
                if (itemName == null || itemName.trim().isEmpty()) {
                    continue;
                }
            }

            StoreOperationalStatisticsVo.PriceListRanking ranking = new StoreOperationalStatisticsVo.PriceListRanking();
            ranking.setPriceId(priceId);
            Map<String, Long> data = entry.getValue();
            ranking.setPageViews(data.getOrDefault("viewCount", 0L));
            ranking.setVisitors(data.getOrDefault("visitorCount", 0L));
            ranking.setShares(data.getOrDefault("shareCount", 0L));
            ranking.setPriceListItemName(itemName != null ? itemName.trim() : null);

            result.add(ranking);
        }
        
        // 按浏览量降序排序
        result.sort((a, b) -> Long.compare(b.getPageViews(), a.getPageViews()));
        
        // 设置排名
        for (int i = 0; i < result.size(); i++) {
            result.get(i).setRank(i + 1);
        }
        
        return result;
    }
    
    // ==================== 工具方法 ====================
    
    /**
     * 判断统计数据是否有效（不全为0）
     * 检查流量数据、互动数据、优惠券数据、代金券数据、服务质量数据、价目表排名数据中是否至少有一个字段不为0
     */
    @SuppressWarnings("unchecked")
    private boolean isStatisticsValid(StoreTrackStatistics stat) {
        if (stat == null) {
            return false;
        }
        
        try {
            // 检查流量数据
            if (stat.getTrafficData() != null && !stat.getTrafficData().isEmpty()) {
                Map<String, Object> trafficData = (Map<String, Object>) JSON.parseObject(stat.getTrafficData(), Map.class);
                if (trafficData != null) {
                    long searchCount = getLongValue(trafficData, "searchCount");
                    long viewCount = getLongValue(trafficData, "viewCount");
                    long visitorCount = getLongValue(trafficData, "visitorCount");
                    long newVisitorCount = getLongValue(trafficData, "newVisitorCount");
                    long totalDuration = getLongValue(trafficData, "totalDuration");
                    if (searchCount > 0 || viewCount > 0 || visitorCount > 0 || newVisitorCount > 0 || totalDuration > 0) {
                        return true;
                    }
                }
            }
            
            // 检查互动数据
            if (stat.getInteractionData() != null && !stat.getInteractionData().isEmpty()) {
                Map<String, Object> interactionData = (Map<String, Object>) JSON.parseObject(stat.getInteractionData(), Map.class);
                if (interactionData != null) {
                    long collectCount = getLongValue(interactionData, "collectCount");
                    long shareCount = getLongValue(interactionData, "shareCount");
                    long checkinCount = getLongValue(interactionData, "checkinCount");
                    long consultCount = getLongValue(interactionData, "consultCount");
                    long friendCount = getLongValue(interactionData, "friendCount");
                    long followCount = getLongValue(interactionData, "followCount");
                    long fansCount = getLongValue(interactionData, "fansCount");
                    long postCount = getLongValue(interactionData, "postCount");
                    long postLikeCount = getLongValue(interactionData, "postLikeCount");
                    long postCommentCount = getLongValue(interactionData, "postCommentCount");
                    long postRepostCount = getLongValue(interactionData, "postRepostCount");
                    if (collectCount > 0 || shareCount > 0 || checkinCount > 0 || consultCount > 0 || 
                        friendCount > 0 || followCount > 0 || fansCount > 0 || postCount > 0 || 
                        postLikeCount > 0 || postCommentCount > 0 || postRepostCount > 0) {
                        return true;
                    }
                }
            }
            
            // 检查优惠券数据
            if (stat.getCouponData() != null && !stat.getCouponData().isEmpty()) {
                Map<String, Object> couponData = (Map<String, Object>) JSON.parseObject(stat.getCouponData(), Map.class);
                if (couponData != null) {
                    long giveToFriendCount = getLongValue(couponData, "giveToFriendCount");
                    BigDecimal giveToFriendAmount = getBigDecimalValue(couponData, "giveToFriendAmount");
                    long friendGiveCount = getLongValue(couponData, "friendGiveCount");
                    BigDecimal friendGiveAmount = getBigDecimalValue(couponData, "friendGiveAmount");
                    if (giveToFriendCount > 0 || giveToFriendAmount.compareTo(BigDecimal.ZERO) > 0 || 
                        friendGiveCount > 0 || friendGiveAmount.compareTo(BigDecimal.ZERO) > 0) {
                        return true;
                    }
                }
            }
            
            // 检查代金券数据
            if (stat.getVoucherData() != null && !stat.getVoucherData().isEmpty()) {
                Map<String, Object> voucherData = (Map<String, Object>) JSON.parseObject(stat.getVoucherData(), Map.class);
                if (voucherData != null) {
                    long giveToFriendCount = getLongValue(voucherData, "giveToFriendCount");
                    BigDecimal giveToFriendAmount = getBigDecimalValue(voucherData, "giveToFriendAmount");
                    long friendGiveCount = getLongValue(voucherData, "friendGiveCount");
                    BigDecimal friendGiveAmount = getBigDecimalValue(voucherData, "friendGiveAmount");
                    if (giveToFriendCount > 0 || giveToFriendAmount.compareTo(BigDecimal.ZERO) > 0 || 
                        friendGiveCount > 0 || friendGiveAmount.compareTo(BigDecimal.ZERO) > 0) {
                        return true;
                    }
                }
            }
            
            // 检查服务质量数据
            if (stat.getServiceData() != null && !stat.getServiceData().isEmpty()) {
                Map<String, Object> serviceData = (Map<String, Object>) JSON.parseObject(stat.getServiceData(), Map.class);
                if (serviceData != null) {
                    double storeScore = getBigDecimalValue(serviceData, "storeScore").doubleValue();
                    long ratingCount = getLongValue(serviceData, "ratingCount");
                    long appealCount = getLongValue(serviceData, "appealCount");
                    if (storeScore > 0 || ratingCount > 0 || appealCount > 0) {
                        return true;
                    }
                }
            }
            
            // 检查价目表排名数据
            if (stat.getPriceRankingData() != null && !stat.getPriceRankingData().isEmpty()) {
                List<Map<String, Object>> priceRankingData = (List<Map<String, Object>>) (List<?>) JSON.parseArray(stat.getPriceRankingData());
                if (priceRankingData != null && !priceRankingData.isEmpty()) {
                    for (Map<String, Object> item : priceRankingData) {
                        long viewCount = getLongValue(item, "viewCount");
                        long visitorCount = getLongValue(item, "visitorCount");
                        long shareCount = getLongValue(item, "shareCount");
                        if (viewCount > 0 || visitorCount > 0 || shareCount > 0) {
                            return true;
                        }
                    }
                }
            }
            
            return false;
        } catch (Exception e) {
            log.warn("判断统计数据有效性失败: {}", e.getMessage(), e);
            // 如果解析失败，认为数据无效
            return false;
        }
    }
    
    /**
     * 从Map中获取Long值
     */
    private Long getLongValue(Map<String, Object> map, String key) {
        Object value = map.get(key);
        if (value == null) return 0L;
        if (value instanceof Long) return (Long) value;
        if (value instanceof Number) return ((Number) value).longValue();
        try {
            return Long.parseLong(value.toString());
        } catch (Exception e) {
            return 0L;
        }
    }
    
    /**
     * 从Map中获取Integer值
     */
    private Integer getIntegerValue(Map<String, Object> map, String key) {
        Object value = map.get(key);
        if (value == null) return null;
        if (value instanceof Integer) return (Integer) value;
        if (value instanceof Number) return ((Number) value).intValue();
        try {
            return Integer.parseInt(value.toString());
        } catch (Exception e) {
            return null;
        }
    }
    
    /**
     * 从Map中获取BigDecimal值
     */
    private BigDecimal getBigDecimalValue(Map<String, Object> map, String key) {
        Object value = map.get(key);
        if (value == null) return BigDecimal.ZERO;
        if (value instanceof BigDecimal) return (BigDecimal) value;
        if (value instanceof Number) return BigDecimal.valueOf(((Number) value).doubleValue());
        try {
            return new BigDecimal(value.toString());
        } catch (Exception e) {
            return BigDecimal.ZERO;
        }
    }
    
    // ==================== 从JSON/Map直接转换的方法 ====================
    
    /**
     * 从Map转换为流量数据VO
     */
    private StoreOperationalStatisticsVo.TrafficData convertToTrafficDataVoFromMap(Map<String, Object> trafficDataMap) {
        StoreOperationalStatisticsVo.TrafficData vo = new StoreOperationalStatisticsVo.TrafficData();
        vo.setStoreSearchVolume(getLongValue(trafficDataMap, "searchCount"));
        vo.setPageViews(getLongValue(trafficDataMap, "viewCount"));
        vo.setVisitors(getLongValue(trafficDataMap, "visitorCount"));
        vo.setNewVisitors(getLongValue(trafficDataMap, "newVisitorCount"));
        // 访问时长从毫秒转换为秒
        Long totalDuration = getLongValue(trafficDataMap, "totalDuration");
        vo.setVisitDuration(totalDuration / 1000);
        Long avgDuration = getLongValue(trafficDataMap, "avgDuration");
        vo.setAvgVisitDuration(avgDuration / 1000);
        return vo;
    }
    
    /**
     * 从JSON字符串转换为互动数据VO
     */
    @SuppressWarnings("unchecked")
    private StoreOperationalStatisticsVo.InteractionData convertToInteractionDataVoFromJson(String interactionDataJson) {
        try {
            Map<String, Object> data = (Map<String, Object>) JSON.parseObject(interactionDataJson, Map.class);
            if (data == null) return new StoreOperationalStatisticsVo.InteractionData();
            
            StoreOperationalStatisticsVo.InteractionData vo = new StoreOperationalStatisticsVo.InteractionData();
            vo.setStoreCollectionCount(getLongValue(data, "collectCount"));
            vo.setStoreShareCount(getLongValue(data, "shareCount"));
            vo.setStoreCheckInCount(getLongValue(data, "checkinCount"));
            vo.setConsultMerchantCount(getLongValue(data, "consultCount"));
            vo.setFriendsCount(getLongValue(data, "friendCount"));
            vo.setFollowCount(getLongValue(data, "followCount"));
            vo.setFansCount(getLongValue(data, "fansCount"));
            vo.setPostsPublishedCount(getLongValue(data, "postCount"));
            vo.setPostLikesCount(getLongValue(data, "postLikeCount"));
            vo.setPostCommentsCount(getLongValue(data, "postCommentCount"));
            vo.setPostSharesCount(getLongValue(data, "postRepostCount"));
            vo.setReportedCount(getLongValue(data, "reportCount"));
            vo.setBlockedCount(getLongValue(data, "blockCount"));
            return vo;
        } catch (Exception e) {
            log.warn("解析互动数据失败: {}", interactionDataJson, e);
            return new StoreOperationalStatisticsVo.InteractionData();
        }
    }
    
    /**
     * 从JSON字符串转换为优惠券数据VO
     */
    @SuppressWarnings("unchecked")
    private StoreOperationalStatisticsVo.CouponData convertToCouponDataVoFromJson(String couponDataJson) {
        try {
            Map<String, Object> data = (Map<String, Object>) JSON.parseObject(couponDataJson, Map.class);
            if (data == null) return new StoreOperationalStatisticsVo.CouponData();
            
            StoreOperationalStatisticsVo.CouponData vo = new StoreOperationalStatisticsVo.CouponData();
            vo.setGiftToFriendsCount(getLongValue(data, "giveToFriendCount"));
            vo.setGiftToFriendsAmount(getBigDecimalValue(data, "giveToFriendAmount"));
            vo.setGiftToFriendsUsedCount(getLongValue(data, "giveToFriendUseCount"));
            vo.setGiftToFriendsUsedAmount(getBigDecimalValue(data, "giveToFriendUseAmount"));
            
            // 使用金额占比
            Object useAmountPercent = data.get("giveToFriendUseAmountPercent");
            if (useAmountPercent != null) {
                if (useAmountPercent instanceof Number) {
                    vo.setGiftToFriendsUsedAmountRatio(BigDecimal.valueOf(((Number) useAmountPercent).doubleValue()));
                } else {
                    vo.setGiftToFriendsUsedAmountRatio(new BigDecimal(useAmountPercent.toString()));
                }
            } else {
                vo.setGiftToFriendsUsedAmountRatio(BigDecimal.ZERO);
            }
            
            vo.setFriendsGiftCount(getLongValue(data, "friendGiveCount"));
            vo.setFriendsGiftAmount(getBigDecimalValue(data, "friendGiveAmount"));
            vo.setFriendsGiftUsedCount(getLongValue(data, "friendGiveUseCount"));
            vo.setFriendsGiftUsedAmount(getBigDecimalValue(data, "friendGiveUseAmount"));
            
            // 好友赠送使用金额占比
            Object friendUseAmountPercent = data.get("friendGiveUseAmountPercent");
            if (friendUseAmountPercent != null) {
                if (friendUseAmountPercent instanceof Number) {
                    vo.setFriendsGiftUsedAmountRatio(BigDecimal.valueOf(((Number) friendUseAmountPercent).doubleValue()));
                } else {
                    vo.setFriendsGiftUsedAmountRatio(new BigDecimal(friendUseAmountPercent.toString()));
                }
            } else {
                vo.setFriendsGiftUsedAmountRatio(BigDecimal.ZERO);
            }
            
            return vo;
        } catch (Exception e) {
            log.warn("解析优惠券数据失败: {}", couponDataJson, e);
            return new StoreOperationalStatisticsVo.CouponData();
        }
    }
    
    /**
     * 从JSON字符串转换为代金券数据VO
     */
    @SuppressWarnings("unchecked")
    private StoreOperationalStatisticsVo.VoucherData convertToVoucherDataVoFromJson(String voucherDataJson) {
        try {
            Map<String, Object> data = (Map<String, Object>) JSON.parseObject(voucherDataJson, Map.class);
            if (data == null) return new StoreOperationalStatisticsVo.VoucherData();
            
            StoreOperationalStatisticsVo.VoucherData vo = new StoreOperationalStatisticsVo.VoucherData();
            vo.setGiftToFriendsCount(getLongValue(data, "giveToFriendCount"));
            vo.setGiftToFriendsAmount(getBigDecimalValue(data, "giveToFriendAmount"));
            vo.setGiftToFriendsUsedCount(getLongValue(data, "giveToFriendUseCount"));
            vo.setGiftToFriendsUsedAmount(getBigDecimalValue(data, "giveToFriendUseAmount"));
            
            // 使用金额占比
            Object useAmountPercent = data.get("giveToFriendUseAmountPercent");
            if (useAmountPercent != null) {
                if (useAmountPercent instanceof Number) {
                    vo.setGiftToFriendsUsedAmountRatio(BigDecimal.valueOf(((Number) useAmountPercent).doubleValue()));
                } else {
                    vo.setGiftToFriendsUsedAmountRatio(new BigDecimal(useAmountPercent.toString()));
                }
            } else {
                vo.setGiftToFriendsUsedAmountRatio(BigDecimal.ZERO);
            }
            
            vo.setFriendsGiftCount(getLongValue(data, "friendGiveCount"));
            vo.setFriendsGiftAmount(getBigDecimalValue(data, "friendGiveAmount"));
            vo.setFriendsGiftUsedCount(getLongValue(data, "friendGiveUseCount"));
            vo.setFriendsGiftUsedAmount(getBigDecimalValue(data, "friendGiveUseAmount"));
            
            // 好友赠送使用金额占比
            Object friendUseAmountPercent = data.get("friendGiveUseAmountPercent");
            if (friendUseAmountPercent != null) {
                if (friendUseAmountPercent instanceof Number) {
                    vo.setFriendsGiftUsedAmountRatio(BigDecimal.valueOf(((Number) friendUseAmountPercent).doubleValue()));
                } else {
                    vo.setFriendsGiftUsedAmountRatio(new BigDecimal(friendUseAmountPercent.toString()));
                }
            } else {
                vo.setFriendsGiftUsedAmountRatio(BigDecimal.ZERO);
            }
            
            return vo;
        } catch (Exception e) {
            log.warn("解析代金券数据失败: {}", voucherDataJson, e);
            return new StoreOperationalStatisticsVo.VoucherData();
        }
    }
    
    /**
     * 从JSON字符串转换为服务质量数据VO
     */
    @SuppressWarnings("unchecked")
    private StoreOperationalStatisticsVo.ServiceQualityData convertToServiceQualityDataVoFromJson(String serviceDataJson) {
        try {
            Map<String, Object> data = (Map<String, Object>) JSON.parseObject(serviceDataJson, Map.class);
            if (data == null) return new StoreOperationalStatisticsVo.ServiceQualityData();
            
            StoreOperationalStatisticsVo.ServiceQualityData vo = new StoreOperationalStatisticsVo.ServiceQualityData();
            
            // 评分字段
            Object storeScore = data.get("storeScore");
            if (storeScore != null) {
                if (storeScore instanceof Number) {
                    vo.setStoreRating(BigDecimal.valueOf(((Number) storeScore).doubleValue()).setScale(1, RoundingMode.HALF_UP));
                } else {
                    vo.setStoreRating(new BigDecimal(storeScore.toString()).setScale(1, RoundingMode.HALF_UP));
                }
            } else {
                vo.setStoreRating(BigDecimal.ZERO);
            }
            
            Object scoreOne = data.get("scoreOne");
            if (scoreOne != null) {
                if (scoreOne instanceof Number) {
                    vo.setScoreOne(BigDecimal.valueOf(((Number) scoreOne).doubleValue()).setScale(1, RoundingMode.HALF_UP));
                } else {
                    vo.setScoreOne(new BigDecimal(scoreOne.toString()).setScale(1, RoundingMode.HALF_UP));
                }
            } else {
                vo.setScoreOne(BigDecimal.ZERO);
            }
            
            Object scoreTwo = data.get("scoreTwo");
            if (scoreTwo != null) {
                if (scoreTwo instanceof Number) {
                    vo.setScoreTwo(BigDecimal.valueOf(((Number) scoreTwo).doubleValue()).setScale(1, RoundingMode.HALF_UP));
                } else {
                    vo.setScoreTwo(new BigDecimal(scoreTwo.toString()).setScale(1, RoundingMode.HALF_UP));
                }
            } else {
                vo.setScoreTwo(BigDecimal.ZERO);
            }
            
            Object scoreThree = data.get("scoreThree");
            if (scoreThree != null) {
                if (scoreThree instanceof Number) {
                    vo.setScoreThree(BigDecimal.valueOf(((Number) scoreThree).doubleValue()).setScale(1, RoundingMode.HALF_UP));
                } else {
                    vo.setScoreThree(new BigDecimal(scoreThree.toString()).setScale(1, RoundingMode.HALF_UP));
                }
            } else {
                vo.setScoreThree(BigDecimal.ZERO);
            }
            
            vo.setTotalReviews(getLongValue(data, "ratingCount"));
            vo.setPositiveReviews(getLongValue(data, "goodRatingCount"));
            vo.setNeutralReviews(getLongValue(data, "midRatingCount"));
            vo.setNegativeReviews(getLongValue(data, "badRatingCount"));
            
            // 差评占比
            Object badRatingPercent = data.get("badRatingPercent");
            if (badRatingPercent != null) {
                if (badRatingPercent instanceof Number) {
                    vo.setNegativeReviewRatio(BigDecimal.valueOf(((Number) badRatingPercent).doubleValue()).setScale(2, RoundingMode.HALF_UP));
                } else {
                    vo.setNegativeReviewRatio(new BigDecimal(badRatingPercent.toString()).setScale(2, RoundingMode.HALF_UP));
                }
            } else {
                vo.setNegativeReviewRatio(BigDecimal.ZERO);
            }
            
            vo.setNegativeReviewAppealsCount(getLongValue(data, "appealCount"));
            vo.setNegativeReviewAppealsSuccessCount(getLongValue(data, "appealSuccessCount"));
            
            // 申诉成功占比
            Object appealSuccessPercent = data.get("appealSuccessPercent");
            if (appealSuccessPercent != null) {
                if (appealSuccessPercent instanceof Number) {
                    vo.setNegativeReviewAppealsSuccessRatio(BigDecimal.valueOf(((Number) appealSuccessPercent).doubleValue()).setScale(2, RoundingMode.HALF_UP));
                } else {
                    vo.setNegativeReviewAppealsSuccessRatio(new BigDecimal(appealSuccessPercent.toString()).setScale(2, RoundingMode.HALF_UP));
                }
            } else {
                vo.setNegativeReviewAppealsSuccessRatio(BigDecimal.ZERO);
            }
            
            return vo;
        } catch (Exception e) {
            log.warn("解析服务质量数据失败: {}", serviceDataJson, e);
            return new StoreOperationalStatisticsVo.ServiceQualityData();
        }
    }
    
    /**
     * 从JSON字符串转换为价目表排名数据VO
     */
    @SuppressWarnings("unchecked")
    private List<StoreOperationalStatisticsVo.PriceListRanking> convertToPriceListRankingVoFromJson(String priceRankingDataJson, Integer storeId) {
        List<StoreOperationalStatisticsVo.PriceListRanking> result = new ArrayList<>();
        
        try {
            List<Map<String, Object>> dataList = (List<Map<String, Object>>) (List<?>) JSON.parseArray(priceRankingDataJson);
            if (dataList == null || dataList.isEmpty()) {
                return result;
            }
            
            // 批量查询价目表名称
            List<Integer> priceIds = new ArrayList<>();
            for (Map<String, Object> item : dataList) {
                Integer priceId = getIntegerValue(item, "priceId");
                if (priceId != null) {
                    priceIds.add(priceId);
                }
            }
            
            Map<Integer, String> priceNameMap = new HashMap<>();
            if (!priceIds.isEmpty() && storeId != null) {
                // 查询店铺信息，获取business_section
                StoreInfo storeInfo = storeInfoMapper.selectById(storeId);
                if (storeInfo != null && storeInfo.getBusinessSection() != null && storeInfo.getBusinessSection() == 1) {
                    // business_section = 1 表示美食，查询美食价目表
                    LambdaQueryWrapper<StoreCuisine> cuisineWrapper = new LambdaQueryWrapper<>();
                    cuisineWrapper.in(StoreCuisine::getId, priceIds)
                                .eq(StoreCuisine::getStoreId, storeId)
                                .eq(StoreCuisine::getDeleteFlag, 0);
                    List<StoreCuisine> cuisines = storeCuisineMapper.selectList(cuisineWrapper);
                    for (StoreCuisine cuisine : cuisines) {
                        if (cuisine.getId() != null && cuisine.getName() != null) {
                            priceNameMap.put(cuisine.getId(), cuisine.getName());
                        }
                    }
                } else {
                    // 其他情况查询通用价目表
                    LambdaQueryWrapper<StorePrice> priceWrapper = new LambdaQueryWrapper<>();
                    priceWrapper.in(StorePrice::getId, priceIds)
                                .eq(StorePrice::getStoreId, storeId)
                                .eq(StorePrice::getDeleteFlag, 0);
                    List<StorePrice> prices = storePriceMapper.selectList(priceWrapper);
                    for (StorePrice price : prices) {
                        if (price.getId() != null && price.getName() != null) {
                            priceNameMap.put(price.getId(), price.getName());
                        }
                    }
                }
            }
            
            // 转换为VO列表（能按店铺查库时：仅保留仍有效的价目/菜品；已删除或查无此条的不展示）
            for (Map<String, Object> item : dataList) {
                Integer priceId = getIntegerValue(item, "priceId");
                if (priceId == null) {
                    continue;
                }
                String priceListItemName = priceNameMap.get(priceId);
                if (storeId != null) {
                    if (priceListItemName == null || priceListItemName.trim().isEmpty()) {
                        continue;
                    }
                }

                StoreOperationalStatisticsVo.PriceListRanking ranking = new StoreOperationalStatisticsVo.PriceListRanking();
                ranking.setPriceId(priceId);
                ranking.setPageViews(getLongValue(item, "viewCount"));
                ranking.setVisitors(getLongValue(item, "visitorCount"));
                ranking.setShares(getLongValue(item, "shareCount"));
                ranking.setPriceListItemName(priceListItemName != null ? priceListItemName.trim() : null);

                result.add(ranking);
            }
            
            // 按浏览量降序排序
            result.sort((a, b) -> Long.compare(b.getPageViews(), a.getPageViews()));
            
            // 设置排名
            for (int i = 0; i < result.size(); i++) {
                result.get(i).setRank(i + 1);
            }
            
        } catch (Exception e) {
            log.warn("解析价目表排名数据失败: {}", priceRankingDataJson, e);
        }
        
        return result;
    }

    @Override
    public String generateStatisticsComparisonPdf(Integer storeId, String currentStartTime, String currentEndTime,
                                                   String previousStartTime, String previousEndTime) {
        log.info("StoreOperationalStatisticsServiceImpl.generateStatisticsComparisonPdf - storeId={}, currentStartTime={}, currentEndTime={}, previousStartTime={}, previousEndTime={}",
                storeId, currentStartTime, currentEndTime, previousStartTime, previousEndTime);
        
        // 参数校验
        if (storeId == null || storeId <= 0) {
            throw new IllegalArgumentException("店铺ID不能为空且必须大于0");
        }
        if (currentStartTime == null || currentStartTime.trim().isEmpty()) {
            throw new IllegalArgumentException("当期开始时间不能为空");
        }
        if (currentEndTime == null || currentEndTime.trim().isEmpty()) {
            throw new IllegalArgumentException("当期结束时间不能为空");
        }
        if (previousStartTime == null || previousStartTime.trim().isEmpty()) {
            throw new IllegalArgumentException("上期开始时间不能为空");
        }
        if (previousEndTime == null || previousEndTime.trim().isEmpty()) {
            throw new IllegalArgumentException("上期结束时间不能为空");
        }
        
        try {
            // 1. 获取统计数据对比（不保存历史记录，因为后面会保存带PDF URL的记录）
            StoreOperationalStatisticsComparisonVo comparison = getStatisticsComparisonWithoutSave(
                    storeId, currentStartTime, currentEndTime, previousStartTime, previousEndTime);
            
            // 2. 生成图片
            byte[] imageBytes = StatisticsComparisonImageUtil.generateImage(comparison);
            
            // 3. 将图片转换为PDF
            java.io.ByteArrayInputStream imageInputStream = new java.io.ByteArrayInputStream(imageBytes);
            byte[] pdfBytes = ImageToPdfUtil.imageToPdfBytes(imageInputStream);
            
            if (pdfBytes == null || pdfBytes.length == 0) {
                throw new RuntimeException("图片转PDF失败");
            }
            
            // 4. 上传PDF到OSS
            String ossFilePath = "statistics/comparison_" + storeId + "_" + RandomCreateUtil.getRandomNum(8) + ".pdf";
            java.io.ByteArrayInputStream pdfInputStream = new java.io.ByteArrayInputStream(pdfBytes);
            String pdfUrl = aliOSSUtil.uploadFile(pdfInputStream, ossFilePath);
            
            log.info("统计数据对比图片转PDF并上传成功 - storeId={}, pdfUrl={}", storeId, pdfUrl);
            
            // 5. 保存对比数据到历史表（包含所有入参和PDF URL）
            saveStatisticsHistory(storeId, currentStartTime, currentEndTime, 
                    previousStartTime, previousEndTime, comparison, pdfUrl);

            return pdfUrl;
        } catch (Exception e) {
            log.error("生成统计数据对比图片并转PDF上传失败 - storeId={}, error={}", storeId, e.getMessage(), e);
            throw new RuntimeException("生成图片并转PDF上传失败: " + e.getMessage(), e);
        }
    }

    @Override
    public String generateStatisticsComparisonPdfByHistoryId(Integer storeId, Integer historyId) {
        log.info("StoreOperationalStatisticsServiceImpl.generateStatisticsComparisonPdfByHistoryId - storeId={}, historyId={}", storeId, historyId);

        if (storeId == null || storeId <= 0) {
            throw new IllegalArgumentException("店铺ID不能为空且必须大于0");
        }
        if (historyId == null || historyId <= 0) {
            throw new IllegalArgumentException("历史记录ID不能为空且必须大于0");
        }

        // 1. 根据 historyId 查询历史记录
        StoreOperationalStatisticsHistory history = getHistoryById(historyId);
        if (!storeId.equals(history.getStoreId())) {
            throw new IllegalArgumentException("历史记录与店铺ID不匹配");
        }
        String statisticsDataJson = history.getStatisticsData();
        if (statisticsDataJson == null || statisticsDataJson.trim().isEmpty()) {
            throw new IllegalArgumentException("该历史记录无统计数据(statistics_data为空)");
        }

        // 2. 将 statistics_data 的 JSON 转为 StoreOperationalStatisticsComparisonVo
        StoreOperationalStatisticsComparisonVo comparison = JSON.parseObject(statisticsDataJson.trim(), StoreOperationalStatisticsComparisonVo.class);
        if (comparison == null) {
            throw new RuntimeException("解析统计数据对比JSON失败");
        }

        try {
            // 3. 生成图片
            byte[] imageBytes = StatisticsComparisonImageUtil.generateImage(comparison);
            java.io.ByteArrayInputStream imageInputStream = new java.io.ByteArrayInputStream(imageBytes);
            byte[] pdfBytes = ImageToPdfUtil.imageToPdfBytes(imageInputStream);
            if (pdfBytes == null || pdfBytes.length == 0) {
                throw new RuntimeException("图片转PDF失败");
            }

            // 4. 上传PDF到OSS
            String ossFilePath = "statistics/comparison_" + storeId + "_" + RandomCreateUtil.getRandomNum(8) + ".pdf";
            java.io.ByteArrayInputStream pdfInputStream = new java.io.ByteArrayInputStream(pdfBytes);
            String pdfUrl = aliOSSUtil.uploadFile(pdfInputStream, ossFilePath);
            log.info("根据历史记录生成统计数据对比PDF并上传成功 - storeId={}, historyId={}, pdfUrl={}", storeId, historyId, pdfUrl);

            // 5. 更新该历史记录的 PDF URL
            updateHistoryPdfUrl(historyId, pdfUrl);
            return pdfUrl;
        } catch (Exception e) {
            log.error("根据历史记录生成统计数据对比PDF失败 - storeId={}, historyId={}, error={}", storeId, historyId, e.getMessage(), e);
            throw new RuntimeException("生成PDF报告失败: " + e.getMessage(), e);
        }
    }

    /**
     * 获取统计数据对比（不保存历史记录）
     * 用于 generateStatisticsComparisonPdf 方法，避免重复保存历史记录
     */
    private StoreOperationalStatisticsComparisonVo getStatisticsComparisonWithoutSave(Integer storeId, String currentStartTime, String currentEndTime,
                                                                                      String previousStartTime, String previousEndTime) {
        StoreOperationalStatisticsComparisonVo comparison = new StoreOperationalStatisticsComparisonVo();
        comparison.setCurrentStartTime(currentStartTime);
        comparison.setCurrentEndTime(currentEndTime);
        comparison.setPreviousStartTime(previousStartTime);
        comparison.setPreviousEndTime(previousEndTime);

        // 获取当期和上期的统计数据
        StoreOperationalStatisticsVo currentStatistics = calculateStatistics(storeId, currentStartTime, currentEndTime);
        StoreOperationalStatisticsVo previousStatistics = calculateStatistics(storeId, previousStartTime, previousEndTime);

        // 构建对比数据
        comparison.setTrafficData(buildTrafficDataComparison(currentStatistics.getTrafficData(), previousStatistics.getTrafficData()));
        comparison.setInteractionData(buildInteractionDataComparison(currentStatistics.getInteractionData(), previousStatistics.getInteractionData()));
        comparison.setCouponData(buildCouponDataComparison(currentStatistics.getCouponData(), previousStatistics.getCouponData()));
        comparison.setVoucherData(buildVoucherDataComparison(currentStatistics.getVoucherData(), previousStatistics.getVoucherData()));
        comparison.setServiceQualityData(buildServiceQualityDataComparison(currentStatistics.getServiceQualityData(), previousStatistics.getServiceQualityData()));
        comparison.setPriceListRanking(buildPriceListRankingComparison(currentStatistics.getPriceListRanking(), previousStatistics.getPriceListRanking(), storeId));

        // 不保存历史记录，由调用方决定是否保存

        return comparison;
    }

    /**
     * 异步调用AI接口进行数据分析
     * 
     * @param historyId 历史记录ID
     * @param storeId 店铺ID
     * @param comparison 统计数据对比
     */
    private void callAiAnalysisAsync(Integer historyId, Integer storeId, StoreOperationalStatisticsComparisonVo comparison) {
        // 如果AI接口URL未配置，跳过调用
        if (!StringUtils.hasText(aiStatisticsAnalysisUrl)) {
            log.warn("AI统计分析接口URL未配置，跳过AI分析 - historyId={}", historyId);
            return;
        }

        try {
            // 获取访问令牌
            String accessToken = aiAuthTokenUtil.getAccessToken();
            if (!StringUtils.hasText(accessToken)) {
                log.error("调用AI分析接口失败，获取accessToken失败 - historyId={}", historyId);
                return;
            }

            // 构建请求体，只发送id
            Map<String, Object> requestBody = new HashMap<>();
            requestBody.put("id", historyId);

            // 构建请求头
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            headers.set("Authorization", "Bearer " + accessToken);

            log.info(requestBody.toString());

            HttpEntity<Map<String, Object>> request = new HttpEntity<>(requestBody, headers);

            log.info("开始调用AI统计分析接口 - historyId={}, storeId={}", historyId, storeId);
            ResponseEntity<String> response = restTemplate.postForEntity(
                    aiStatisticsAnalysisUrl != null ? aiStatisticsAnalysisUrl : "", request, String.class);

            if (response != null && response.getStatusCode() == HttpStatus.OK) {
                String responseBody = response.getBody();
                log.info("AI统计分析接口调用成功 - historyId={}, response={}", historyId, responseBody);
                
                // 解析AI返回的结果
                if (StringUtils.hasText(responseBody)) {
                    try {
                        @SuppressWarnings("unchecked")
                        Map<String, Object> responseMap = (Map<String, Object>) JSON.parseObject(responseBody, Map.class);
                        if (responseMap != null) {
                            String summary = extractStringValue(responseMap, "summary");
                            String optimizationSuggestions = extractStringValue(responseMap, "optimizationSuggestions");
                            
                            // 更新历史记录的AI分析结果
                            if (StringUtils.hasText(summary) || StringUtils.hasText(optimizationSuggestions)) {
                                updateHistoryAiAnalysis(historyId, 1, summary, optimizationSuggestions);
                                log.info("更新AI分析结果成功 - historyId={}", historyId);
                            }
                        }
                    } catch (Exception e) {
                        log.warn("解析AI分析结果失败 - historyId={}, responseBody={}, error={}", 
                                historyId, responseBody, e.getMessage());
                    }
                }
            } else {
                log.warn("AI统计分析接口调用失败 - historyId={}, statusCode={}", 
                        historyId, response != null ? response.getStatusCode() : null);
            }
        } catch (Exception e) {
            log.error("调用AI统计分析接口异常 - historyId={}, error={}", historyId, e.getMessage(), e);
        }
    }

    /**
     * 从Map中提取String值
     */
    private String extractStringValue(Map<String, Object> map, String key) {
        if (map == null) {
            return null;
        }
        Object value = map.get(key);
        if (value == null) {
            return null;
        }
        return value.toString();
    }

}
