package com.hzs.retail.member.utils;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.hzs.common.core.enums.EYesNo;
import com.hzs.common.domain.member.base.CuMember;
import com.hzs.retail.member.param.MarketDynamicsQueryDateParam;
import com.hzs.retail.member.vo.BigAndSmallRangeVO;
import com.hzs.retail.member.vo.CuMemberRetailDataStatisticsDetailVO;
import com.hzs.retail.member.vo.CuMemberRetailDataStatisticsResultVO;
import com.hzs.retail.member.vo.MarketDynamicsDetailVO;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 用户统计数据工具
 * 主要用户统计用户的业绩/盒数/明细等
 * 主要处理的类为
 * @link com.hzs.retail.member.vo.CuMemberRetailDataStatisticsDetailVO
 */
public class DataStatisticsUtil {
    private static final Long SELF_VIRTUAL_ID = -1000L;
    private static final Long BIG_RANGE_VIRTUAL_ID = -2000L;
    private static final Long SMALL_RANGE_VIRTUAL_ID = -3000L;
    private static final String SELF_VIRTUAL_NAME = "个人消费虚拟分支";
    private static final String BIG_RANGE_VIRTUAL_NAME = "注水大区虚拟分支";
    private static final String SMALL_RANGE_VIRTUAL_NAME = "注水小区虚拟分支";

    public static CuMemberRetailDataStatisticsResultVO getCalcMap(List<CuMemberRetailDataStatisticsDetailVO> detailVOList, CuMember cuMember){
        Long pkId = cuMember.getPkId();
        // 非激活直接返0
        // 激活判断上一天的ENABLE_STATUS 0为正常 1为当天激活 不计算日结数据
        if(EYesNo.NO.getIntValue() == cuMember.getIsActivate()){
            return CuMemberRetailDataStatisticsResultVO.builder()
                    .totalBoxNum(BigDecimal.ZERO)
                    .totalPv(BigDecimal.ZERO)
                    .bigRangeTotalBoxNum(BigDecimal.ZERO)
                    .bigRangeTotalPv(BigDecimal.ZERO)
                    .smallRangeTotalBoxNum(BigDecimal.ZERO)
                    .smallRangeTotalPv(BigDecimal.ZERO)
                    .build();
        }
        calcDetailVOTotalField(detailVOList, pkId);
        addVirtualBranch(detailVOList, pkId);
        CuMemberRetailDataStatisticsDetailVO total = getDetailVOByPKID(detailVOList, pkId);
        if(EYesNo.NO.getIntValue() == cuMember.getIsActivate()){
            // 昨日非激活 排除昨日日结表数据
            excludeDailySettlementData(detailVOList);
        }
        else{
            // 排除注水数据
            excludeWaterInjectionData(detailVOList, pkId);
        }
        CuMemberRetailDataStatisticsDetailVO bigRangeBox = getBigRangeBoxDetailVO(detailVOList, pkId);
        CuMemberRetailDataStatisticsDetailVO bigRangePv = getBigRangePVDetailVO(detailVOList, pkId);
//        BigDecimal smallRangeTotalBoxNum = total.getTotalBoxNum() - bigRangeBox.getTotalBoxNum();
        BigDecimal smallRangeTotalBoxNum = total.getTotalBoxNum().subtract(bigRangeBox.getTotalBoxNum());
        if(smallRangeTotalBoxNum.compareTo(BigDecimal.ZERO) < 0){
            smallRangeTotalBoxNum = BigDecimal.ZERO;
        }
        BigDecimal smallRangeTotalPv = total.getTotalPv().subtract(bigRangePv.getTotalPv());
        if(smallRangeTotalPv.compareTo(BigDecimal.ZERO) < 0){
            smallRangeTotalPv = BigDecimal.ZERO;
        }
        return CuMemberRetailDataStatisticsResultVO.builder()
                .totalBoxNum(total.getTotalBoxNum())
                .totalPv(formatPV(total.getTotalPv()))
                .bigRangeTotalBoxNum(bigRangeBox.getTotalBoxNum())
                .bigRangeTotalPv(formatPV(bigRangePv.getTotalPv()))
                .smallRangeTotalBoxNum(smallRangeTotalBoxNum)
                .smallRangeTotalPv(formatPV(smallRangeTotalPv))
                .build();
    }
    /**
     * 计算集合内数据总数
     * @param detailVOList
     */
    public static void calcDetailVOTotalField(List<CuMemberRetailDataStatisticsDetailVO> detailVOList, Long pkId){
        detailVOList.stream().forEach(detailVO -> {
            detailVO.setTotalBoxNum(
                    detailVO.getConsumeBoxNum()
                    .add(detailVO.getTeamBoxNum())
                    .add(detailVO.getSNewBoxNum())
                    .add(detailVO.getSTeamNewBoxNum())
                    .add(detailVO.getBigBoxNum())
                    .add(detailVO.getSmallBoxNum())
            );
//            detailVO.setTotalBoxNum(
//                    detailVO.getConsumeBoxNum()         // 个人累计消费盒数(日结)
////                     + detailVO.getNewBoxNum()          // 个人新增盒数(日结)
//                     + detailVO.getTeamBoxNum()         // 团队累计消费盒数(日结)
////                     + detailVO.getTeamNewBoxNum()      // 团队新增盒数(日结)
//                     + detailVO.getSNewBoxNum()         // 个人新增消费盒数(秒结)
//                     + detailVO.getSTeamNewBoxNum()     // 团队新增盒数(秒结)
//                     + detailVO.getBigBoxNum()          // 个人注水大区盒数(日结)
//                     + detailVO.getSmallBoxNum()        // 个人注水小区盒数(日结)
//            );
            detailVO.setTotalPv(
                    detailVO.getConsumePv()
//                    .add(detailVO.getNewConsumePv())
                    .add(detailVO.getTeamConsumePv())
//                    .add(detailVO.getTeamNewPv())
                    .add(detailVO.getSNewConsumePv())
                    .add(detailVO.getSTeamNewPv())
            );
        });
    }

    /**
     * 排除昨日日结数据
     * @param detailVOList
     */
    public static void excludeDailySettlementData(List<CuMemberRetailDataStatisticsDetailVO> detailVOList){
        detailVOList.stream().forEach(detailVO -> {
            detailVO.setTotalBoxNum(detailVO.getTotalBoxNum().subtract(detailVO.getTeamBoxNum()));
//            detailVO.setTotalBoxNum(
//                    detailVO.getTotalBoxNum()
//                    - detailVO.getTeamBoxNum()          // 团队累计消费盒数(日结)
//            );
            detailVO.setTotalPv(
                    detailVO.getTotalPv().subtract(detailVO.getTeamConsumePv())
            );
        });
    }

    /**
     * 排除昨日日结注水数据
     * 自己的注水不排除
     * @param detailVOList
     */
    public static void excludeWaterInjectionData(List<CuMemberRetailDataStatisticsDetailVO> detailVOList, Long pkId){
        detailVOList.stream().forEach(detailVO -> {
            if(!detailVO.getPkId().equals(pkId)){
                detailVO.setTotalBoxNum(detailVO.getTotalBoxNum().subtract(detailVO.getBigBoxNum()).subtract(detailVO.getSmallBoxNum()));
//                detailVO.setTotalBoxNum(
//                        detailVO.getTotalBoxNum()
//                                - detailVO.getBigBoxNum()               // 注水大区
//                                - detailVO.getSmallBoxNum()             // 注水小区
//                );
            }
        });
    }

    /**
     * 增加虚拟分支 主要为
     * 1.自己的消费总数
     * 2.注水的大小区
     *
     * @param detailVOList
     */
    public static void addVirtualBranch(List<CuMemberRetailDataStatisticsDetailVO> detailVOList, Long pkId){
        CuMemberRetailDataStatisticsDetailVO detailVO = getDetailVOByPKID(detailVOList, pkId);
        if(ObjectUtil.isNotEmpty(detailVO)){
            CuMemberRetailDataStatisticsDetailVO selfVirtualDetailVO = getCuMemberRetailDataStatisticsDetailVO(detailVO);
            detailVOList.add(selfVirtualDetailVO);
//            if(detailVO.getBigBoxNum() > 0 || detailVO.getSmallBoxNum() > 0){
            if(detailVO.getBigBoxNum().compareTo(BigDecimal.ZERO) >= 0 || detailVO.getSmallBoxNum().compareTo(BigDecimal.ZERO) >= 0){
                CuMemberRetailDataStatisticsDetailVO bigRangeVirtualDetailVO = CuMemberRetailDataStatisticsDetailVO.builder()
                        .pkId(BIG_RANGE_VIRTUAL_ID)
                        .memberCode(BIG_RANGE_VIRTUAL_NAME)
                        .totalBoxNum(detailVO.getBigBoxNum())
                        .totalPv(BigDecimal.ZERO)
                        .bigBoxNum(BigDecimal.ZERO)
                        .smallBoxNum(BigDecimal.ZERO)
                        .build();
                CuMemberRetailDataStatisticsDetailVO smallRangeVirtualDetailVO = CuMemberRetailDataStatisticsDetailVO.builder()
                        .pkId(SMALL_RANGE_VIRTUAL_ID)
                        .memberCode(SMALL_RANGE_VIRTUAL_NAME)
                        .totalBoxNum(detailVO.getSmallBoxNum())
                        .totalPv(BigDecimal.ZERO)
                        .bigBoxNum(BigDecimal.ZERO)
                        .smallBoxNum(BigDecimal.ZERO)
                        .build();
                detailVOList.add(bigRangeVirtualDetailVO);
                detailVOList.add(smallRangeVirtualDetailVO);
            }
        }

    }

    private static CuMemberRetailDataStatisticsDetailVO getCuMemberRetailDataStatisticsDetailVO(CuMemberRetailDataStatisticsDetailVO detailVO) {
        return CuMemberRetailDataStatisticsDetailVO.builder()
                .pkId(SELF_VIRTUAL_ID)
                .memberCode(SELF_VIRTUAL_NAME)
                .totalBoxNum(
                        detailVO.getConsumeBoxNum()
                                .add(detailVO.getSNewBoxNum())
                )
//                .totalBoxNum(
//                        detailVO.getConsumeBoxNum()
////                        + detailVO.getNewBoxNum()
//                        + detailVO.getSNewBoxNum()
//                )
                .totalPv(
                        detailVO.getConsumePv()
                                .add(detailVO.getSNewConsumePv())
                )
                .bigBoxNum(BigDecimal.ZERO)
                .smallBoxNum(BigDecimal.ZERO)
                .build();
    }

    /**
     * 移除总数Top1
     * @param detailVOList
     */
    public static List<CuMemberRetailDataStatisticsDetailVO> getSmallRangeList(List<CuMemberRetailDataStatisticsDetailVO> detailVOList){
        List<CuMemberRetailDataStatisticsDetailVO> result = new ArrayList<>();
        BigDecimal maxTotalBoxNum = getMaxTotalBoxNum(detailVOList);
        if (maxTotalBoxNum == null) {
            return new ArrayList<>(detailVOList);
        }
        boolean removed = false;
        for (CuMemberRetailDataStatisticsDetailVO vo : detailVOList) {
            if (!removed && Objects.equals(vo.getTotalBoxNum(), maxTotalBoxNum)) {
                removed = true;
            } else {
                result.add(vo);
            }
        }
        return result;
    }

    /**
     * 根据ID获取对应数据
     * @param detailVOList
     * @return
     */
    public static CuMemberRetailDataStatisticsDetailVO getDetailVOByPKID(List<CuMemberRetailDataStatisticsDetailVO> detailVOList, Long pkId){
        return detailVOList.stream().filter(o -> o.getPkId().equals(pkId)).findFirst().orElse(null);
    }

    /**
     * 组装市场动态列表数据
     * @param detailVOList
     */
    public static PageResult<MarketDynamicsDetailVO> getMarketDynamicsAssemblyData(List<MarketDynamicsDetailVO> detailVOList, MarketDynamicsQueryDateParam param){
        if(StrUtil.isNotEmpty(param.getKeyWords())){
            detailVOList = detailVOList.stream().filter(o -> o.getMemberCode().contains(param.getKeyWords()) || o.getMemberName().contains(param.getKeyWords())).collect(Collectors.toList());
        }
        MarketDynamicsDetailVO bigRange = null;
        if(param.getQueryType().equals(1)){
            bigRange = detailVOList.stream()
//                    .max(Comparator.comparingInt(MarketDynamicsDetailVO::getTotalBoxNum))
                    .max(Comparator.comparing(MarketDynamicsDetailVO::getTotalBoxNum, BigDecimal::compareTo))
                    .orElse(null);
        }else{
            bigRange = detailVOList.stream()
                    .max(Comparator.comparing(MarketDynamicsDetailVO::getTodayPv))
                    .orElse(null);
        }
        MarketDynamicsDetailVO finalBigRange = bigRange;
        detailVOList = detailVOList.stream().filter(o -> !o.getPkId().equals(finalBigRange.getPkId())).collect(Collectors.toList());
        PageResult<MarketDynamicsDetailVO> result = MemoryPageUtils.paginate(detailVOList, param.getPageNum(), param.getPageSize());
        result.setBigRange(bigRange);
        return result;
    }

    private static BigDecimal getMaxTotalBoxNum(List<CuMemberRetailDataStatisticsDetailVO> detailVOList) {
        return detailVOList.stream()
                .map(CuMemberRetailDataStatisticsDetailVO::getTotalBoxNum)
                .filter(Objects::nonNull)
//                .max(Integer::compare)
                .max(BigDecimal::compareTo)
                .orElse(null);
    }
    private static CuMemberRetailDataStatisticsDetailVO getBigRangeBoxDetailVO(List<CuMemberRetailDataStatisticsDetailVO> detailVOList, Long pkId){
        return detailVOList.stream()
                .filter(vo -> vo.getTotalBoxNum() != null && !vo.getPkId().equals(pkId))
//                .max(Comparator.comparingInt(CuMemberRetailDataStatisticsDetailVO::getTotalBoxNum))
                .max(Comparator.comparing(CuMemberRetailDataStatisticsDetailVO::getTotalBoxNum, BigDecimal::compareTo))
                .orElse(null);
    }
    private static CuMemberRetailDataStatisticsDetailVO getBigRangePVDetailVO(List<CuMemberRetailDataStatisticsDetailVO> detailVOList, Long pkId){
        return detailVOList.stream()
                .filter(vo -> vo.getTotalBoxNum() != null && !vo.getPkId().equals(pkId))
                .max(Comparator.comparing(CuMemberRetailDataStatisticsDetailVO::getTotalPv))
                .orElse(null);
    }
    public static BigDecimal formatPV(BigDecimal pv){
        return pv.divide(
                new BigDecimal("10000"),
                4,
                RoundingMode.FLOOR
        );
    }
    public static void setQueryDateParam(MarketDynamicsQueryDateParam param){
        LocalDate.now(ZoneId.of("Asia/Shanghai"));
        LocalDate currentDate = LocalDate.now();
        LocalDate yesterdayDate = currentDate.minusDays(1);
        LocalDate previousMonthDate = currentDate.minusMonths(1);
        LocalDate lastDayOfPreviousMonth = previousMonthDate.with(TemporalAdjusters.lastDayOfMonth());
        param.setNowDate(currentDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        param.setYesterdayDate(yesterdayDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        param.setLastMonthDate(lastDayOfPreviousMonth.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
//        System.out.println("当前日期: " + currentDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
//        System.out.println("上一个月最后一天: " + lastDayOfPreviousMonth.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
//        return MarketDynamicsQueryDateParam.builder()
//                        .nowDate(currentDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")))
//                                .lastMonthDate(lastDayOfPreviousMonth.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")))
//                                        .build();
    }


    public static CuMemberRetailDataStatisticsDetailVO getBigRangeWithPV(List<CuMemberRetailDataStatisticsDetailVO> detailVOList, CuMember cuMember){
        Long pkId = cuMember.getPkId();
        // 非激活直接返0
        // 激活判断上一天的ENABLE_STATUS 0为正常 1为当天激活 不计算日结数据
        if(EYesNo.NO.getIntValue() == cuMember.getIsActivate()){
            return CuMemberRetailDataStatisticsDetailVO.builder()
                    .build();
        }
        calcDetailVOTotalField(detailVOList, pkId);
        addVirtualBranch(detailVOList, pkId);
        CuMemberRetailDataStatisticsDetailVO total = getDetailVOByPKID(detailVOList, pkId);
        if(EYesNo.NO.getIntValue() == cuMember.getIsActivate()){
            // 昨日非激活 排除昨日日结表数据
            excludeDailySettlementData(detailVOList);
        }
        else{
            // 排除注水数据
            excludeWaterInjectionData(detailVOList, pkId);
        }
        return getBigRangePVDetailVO(detailVOList, pkId);
    }


    public static BigAndSmallRangeVO getBigAndSmallRangeVO(List<CuMemberRetailDataStatisticsDetailVO> detailVOList, CuMember cuMember){
        Long pkId = cuMember.getPkId();
        BigAndSmallRangeVO bigAndSmallRangeVO = new BigAndSmallRangeVO();
        // 非激活直接返0
        // 激活判断上一天的ENABLE_STATUS 0为正常 1为当天激活 不计算日结数据
        if(EYesNo.NO.getIntValue() == cuMember.getIsActivate()){
            return null;
        }
        calcDetailVOTotalField(detailVOList, pkId);
        addVirtualBranch(detailVOList, pkId);
        CuMemberRetailDataStatisticsDetailVO total = getDetailVOByPKID(detailVOList, pkId);
        if(EYesNo.NO.getIntValue() == cuMember.getIsActivate()){
            // 昨日非激活 排除昨日日结表数据
            excludeDailySettlementData(detailVOList);
        }
        else{
            // 排除注水数据
            excludeWaterInjectionData(detailVOList, pkId);
        }
        CuMemberRetailDataStatisticsDetailVO big = getBigRangePVDetailVO(detailVOList, pkId);
        bigAndSmallRangeVO.setBigRangeId(big.getPkId());
        List<Long> smallIdList = detailVOList.stream()
                .map(CuMemberRetailDataStatisticsDetailVO::getPkId).filter(id -> !id.equals(big.getPkId())).collect(Collectors.toList());
        bigAndSmallRangeVO.setSmallRangeId(smallIdList);
        return bigAndSmallRangeVO;
    }
}
