package com.czg.service.order.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.czg.exception.CzgException;
import com.czg.order.entity.ShopProdStatistic;
import com.czg.order.param.SaleSummaryCountParam;
import com.czg.order.service.ShopProdStatisticService;
import com.czg.order.vo.SaleSummaryCountVo;
import com.czg.service.order.mapper.ShopProdStatisticMapper;
import com.czg.utils.CzgStrUtils;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 商品统计表 服务层实现。
 *
 * @author ww
 * @since 2025-11-21
 */
@Service
public class ShopProdStatisticServiceImpl extends ServiceImpl<ShopProdStatisticMapper, ShopProdStatistic> implements ShopProdStatisticService {

    @Override
    public List<ShopProdStatistic> getArchiveTradeDataBy10(Long shopId, Integer day) {
        LocalDate currentDate = LocalDate.now();
        LocalDate startDate = currentDate.minusDays(day - 1);
        List<ShopProdStatistic> archiveTradeData = getArchiveTradeData(new SaleSummaryCountParam()
                .setShopId(shopId).setProductName(null).setRangeType("").setBeginDate(startDate)
                .setEndDate(currentDate).setCategoryId(0L));
        // 按照 saleCount 降序排序
        return archiveTradeData.stream()
                .sorted(
                        Comparator.comparing(
                                ShopProdStatistic::getSaleCount,
                                Comparator.nullsLast(BigDecimal::compareTo).reversed()
                        )
                )
                .limit(10)
                .toList();

    }


    @Override
    public SaleSummaryCountVo summaryCount(SaleSummaryCountParam param) {
        LocalDate currentDate = LocalDate.now();
        if ("today".equals(param.getRangeType())) {
            return mapper.summaryCountByDay(param.getShopId(), currentDate, param.getProductName(), param.getCategoryId());
        }
        if ("yesterday".equals(param.getRangeType())) {
            return mapper.summaryCountSingleDate(param.getShopId(), currentDate.minusDays(1), param.getProductName(), param.getCategoryId());
        }

        if (param.getBeginDate().isAfter(currentDate)) {
            throw new CzgException("开始时间不能晚于当前时间");
        }
        if (param.getBeginDate().equals(param.getEndDate())) {
            return mapper.summaryCountSingleDate(param.getShopId(), param.getBeginDate(), param.getProductName(), param.getCategoryId());
        }
        if (param.getEndDate().isBefore(currentDate)) {
            return mapper.summaryCountDateRange(param.getShopId(), param.getBeginDate(), param.getEndDate(), param.getProductName(), param.getCategoryId());
        }
        SaleSummaryCountVo todaySummary = mapper.summaryCountByDay(param.getShopId(), currentDate, param.getProductName(), param.getCategoryId());
        SaleSummaryCountVo dateRangeSummary = mapper.summaryCountDateRange(param.getShopId(), param.getBeginDate(), param.getEndDate(), param.getProductName(), param.getCategoryId());
        return mergeSummaryCountVo(todaySummary, dateRangeSummary);
    }

    @Override
    public List<ShopProdStatistic> getArchiveTradeData(SaleSummaryCountParam param) {
        LocalDate currentDate = LocalDate.now();
        param.setProductName(CzgStrUtils.getStrOrNull(param.getProductName()));
        if ("today".equals(param.getRangeType())) {
            return getRealTimeDataByDay(param.getShopId(), currentDate, param.getProductName(), param.getCategoryId());
        }

        if ("yesterday".equals(param.getRangeType())) {
            return getProdStatSingleDate(param.getShopId(), currentDate.minusDays(1),
                    param.getProductName(), param.getCategoryId());
        }

        if (param.getBeginDate().isAfter(currentDate)) {
            throw new CzgException("开始时间不能晚于当前时间");
        }
        if (param.getBeginDate().equals(param.getEndDate())) {
            return getProdStatSingleDate(param.getShopId(), param.getBeginDate(), param.getProductName(),
                    param.getCategoryId());
        }
        if (param.getEndDate().isBefore(currentDate)) {
            return getProdStatDateRange(param.getShopId(), param.getBeginDate(), param.getEndDate(),
                    param.getProductName(), param.getCategoryId());
        }
        List<ShopProdStatistic> realTimeDataByDay = getRealTimeDataByDay(param.getShopId(), currentDate,
                param.getProductName(), param.getCategoryId());
        List<ShopProdStatistic> dateRange = getProdStatDateRange(param.getShopId(), param.getBeginDate(),
                param.getEndDate(), param.getProductName(), param.getCategoryId());

        return mergeProdStatistic(realTimeDataByDay, dateRange);
    }


    @Override
    public void statisticAndInsert(Long shopId, LocalDate day, Long categoryId) {
        List<ShopProdStatistic> realTimeData = getRealTimeDataByDay(shopId, day, null, categoryId);
        if (CollUtil.isNotEmpty(realTimeData)) {
            boolean exists = exists(QueryWrapper.create().eq(ShopProdStatistic::getShopId, shopId).eq(ShopProdStatistic::getCreateDay, day));
            if (exists) {
                remove(QueryWrapper.create().eq(ShopProdStatistic::getShopId, shopId).eq(ShopProdStatistic::getCreateDay, day));
            }
            mapper.insertBatchSelective(realTimeData, 50);
        }
    }

    @Override
    public List<ShopProdStatistic> getRealTimeDataByDay(Long shopId, LocalDate day, String productName, Long categoryId) {
        List<ShopProdStatistic> shopProdStatistics = mapper.selectProStatByDay(shopId, day, productName, categoryId);
        // 过滤掉没有有效数据的记录
        shopProdStatistics = shopProdStatistics.stream()
                .filter(ShopProdStatistic::isValid)
                .peek(ShopProdStatistic::initValidData)
                .toList();
        return shopProdStatistics;
    }

    @Override
    public List<ShopProdStatistic> getProdStatSingleDate(Long shopId, LocalDate day, String productName, Long categoryId) {
        return mapper.getProdStatSingleDate(shopId, day, productName, categoryId);
    }

    @Override
    public List<ShopProdStatistic> getProdStatDateRange(Long shopId, LocalDate start, LocalDate end, String productName, Long categoryId) {
        return mapper.getProdStatDateRange(shopId, start, end, productName, categoryId);
    }

    private SaleSummaryCountVo mergeSummaryCountVo(SaleSummaryCountVo todaySummary, SaleSummaryCountVo dateRangeSummary) {
        if (todaySummary == null) {
            todaySummary = new SaleSummaryCountVo();
        }
        if (dateRangeSummary == null) {
            dateRangeSummary = new SaleSummaryCountVo();
        }

        return new SaleSummaryCountVo(
                safeAdd(todaySummary.getTotalAmount(), dateRangeSummary.getTotalAmount()),
                safeAdd(todaySummary.getRefundAmount(), dateRangeSummary.getRefundAmount()),
                safeAdd(todaySummary.getSaleCount(), dateRangeSummary.getSaleCount()),
                safeAdd(todaySummary.getRefundCount(), dateRangeSummary.getRefundCount())
        );
    }


    /**
     * 合并实时数据和日期范围数据
     *
     * @param realTimeDataByDay 实时数据
     * @param dateRange         日期范围数据
     * @return 合并后的数据
     */
    private List<ShopProdStatistic> mergeProdStatistic(List<ShopProdStatistic> realTimeDataByDay, List<ShopProdStatistic> dateRange) {
        if (realTimeDataByDay == null) {
            realTimeDataByDay = new ArrayList<>();
        }
        if (dateRange == null) {
            dateRange = new ArrayList<>();
        }

        return Stream.concat(realTimeDataByDay.stream(), dateRange.stream())
                .filter(Objects::nonNull)
                .collect(Collectors.toMap(
                        ShopProdStatistic::getProdId,
                        Function.identity(),
                        (stat1, stat2) -> {
                            // 创建合并后的对象
                            ShopProdStatistic merged = new ShopProdStatistic();
                            merged.setId(stat1.getId());
                            merged.setShopId(stat1.getShopId());
                            merged.setProdId(stat1.getProdId());
                            merged.setProductName(stat1.getProductName());

                            // 安全处理BigDecimal相加，处理null值
                            merged.setSaleCount(safeAdd(stat1.getSaleCount(), stat2.getSaleCount()));
                            merged.setSaleAmount(safeAdd(stat1.getSaleAmount(), stat2.getSaleAmount()));
                            merged.setRefundCount(safeAdd(stat1.getRefundCount(), stat2.getRefundCount()));
                            merged.setRefundAmount(safeAdd(stat1.getRefundAmount(), stat2.getRefundAmount()));

                            return merged;
                        }
                ))
                .values()
                .stream()
                .toList();
    }


    private BigDecimal safeAdd(BigDecimal num1, BigDecimal num2) {
        BigDecimal safeNum1 = num1 != null ? num1 : BigDecimal.ZERO;
        BigDecimal safeNum2 = num2 != null ? num2 : BigDecimal.ZERO;
        return safeNum1.add(safeNum2);
    }
}
