package shop.alien.storeplatform.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.storeplatform.service.PlatformStoreOperationalStatisticsService;
import shop.alien.storeplatform.util.PlatformStatisticsComparisonImageUtil;
import shop.alien.storeplatform.util.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 PlatformStoreOperationalStatisticsServiceImpl implements PlatformStoreOperationalStatisticsService {

    private final LifeBrowseRecordMapper lifeBrowseRecordMapper;
    private final LifeCollectMapper lifeCollectMapper;
    private final StoreClockInMapper storeClockInMapper;
    private final LifeUserDynamicsMapper lifeUserDynamicsMapper;
    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 RestTemplate restTemplate;
    private final AiAuthTokenUtil aiAuthTokenUtil;


    @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 getPlatformStatisticsInTrackFormat(Integer storeId, String startTime, String endTime) {
        log.info("StoreOperationalStatisticsServiceImpl.getStatisticsInTrackFormat - storeId={}, startTime={}, endTime={}", 
                storeId, startTime, endTime);
        
        // 计算统计数据
        StoreOperationalStatisticsVo statistics = calculateStatistics(storeId, startTime, endTime);
        
        // 不再保存统计数据到历史表，只有对比接口才会保存历史数据
        
        return statistics;
    }

    @Override
    public StoreOperationalStatisticsComparisonVo getPlatformStatisticsComparison(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 StoreOperationalStatisticsHistory getPlatformHistoryById(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 IPage<StoreOperationalStatisticsHistory> getPlatformHistoryList(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 boolean batchPlatformDeleteHistory(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 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 = PlatformStatisticsComparisonImageUtil.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);
        }
    }

    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;
        }
    }


    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;
    }

    /**
     * 构建流量数据对比
     */
    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;
    }

    /**
     * 异步调用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);
        }
    }

    /**
     * 构建对比数据
     */
    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;
        }
    }

    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;
        }
    }

    /**
     * 从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();
    }

    /**
     * 保存对比统计数据到历史表
     * @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;
        }
    }


    /**
     * 计算统计数据（从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;
    }

    // ==================== 工具方法 ====================

    /**
     * 判断统计数据是否有效（不全为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;
        }
    }

    // ==================== 从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;
    }

    /**
     * 从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;
        }
    }

    /**
     * 从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;
        }
    }
}
