package com.bonus.material.main.service.impl;

import com.bonus.common.biz.domain.lease.LeasePublishInfo;
import com.bonus.common.core.web.domain.AjaxResult;
import com.bonus.material.main.domain.DemandAndSupplyVo;
import com.bonus.material.main.domain.MaTypeHomeVo;
import com.bonus.material.main.mapper.MainMapper;
import com.bonus.material.main.service.MainService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

import static com.bonus.common.core.web.domain.AjaxResult.success;

@Service
@Slf4j
public class MainServiceImpl implements MainService {

    @Resource
    private MainMapper mainMapper;

    /**
     * 需求量
     * @param demandAndSupplyVo
     * @return
     */
    @Override
    public BigDecimal getDemandNum(DemandAndSupplyVo demandAndSupplyVo) {
        //获取领料的需求数量
        LeasePublishInfo leasePublishInfo = mainMapper.getPublishList(demandAndSupplyVo);
        BigDecimal preCountNum = leasePublishInfo.getPreCountNum();
        //获取领用的需求数量
        BigDecimal preCountNumNew = mainMapper.getPublishListNew(demandAndSupplyVo);
        preCountNum = preCountNum.add(preCountNumNew);
        return preCountNum;
    }

    /**
     * 需求增长量
     * @param demandAndSupplyVo
     * @return
     */
    @Override
    public BigDecimal getDemandIncrease(DemandAndSupplyVo demandAndSupplyVo) {
        DemandAndSupplyVo demandAndSupplyVoNew = new DemandAndSupplyVo();
        BeanUtils.copyProperties(demandAndSupplyVo,demandAndSupplyVoNew);
        // 定义日期格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        //上个月的开始时间
        LocalDate startTime = LocalDate.parse(demandAndSupplyVo.getStartTime(), formatter);
        LocalDate lastStartTime = startTime.minusMonths(1);
        String lastStartTimeStr = lastStartTime.format(formatter);
        //上个月的结束时间
        LocalDate endTime = LocalDate.parse(demandAndSupplyVo.getEndTime(), formatter);
        LocalDate lastEndTime = endTime.minusMonths(1);
        String lastEndTimeStr = lastEndTime.format(formatter);
        //获取本月的需求数量
        BigDecimal  preCountNum= this.getDemandNum(demandAndSupplyVoNew);
        //获取上个月需求量
        demandAndSupplyVoNew.setStartTime(lastStartTimeStr);
        demandAndSupplyVoNew.setEndTime(lastEndTimeStr);
        BigDecimal lastPreCountNum = this.getDemandNum(demandAndSupplyVoNew);
        //计算增长量
        BigDecimal demandIncrease= BigDecimal.ZERO;
        if (lastPreCountNum.compareTo(BigDecimal.ZERO)==0 && preCountNum.compareTo(BigDecimal.ZERO) > 0){
            demandIncrease = BigDecimal.valueOf(100);
        }else if (preCountNum.compareTo(BigDecimal.ZERO)==0 && lastPreCountNum.compareTo(BigDecimal.ZERO) > 0){
            demandIncrease = BigDecimal.valueOf(-100);
        }else if (lastPreCountNum.compareTo(BigDecimal.ZERO) > 0){
            demandIncrease = preCountNum.subtract(lastPreCountNum).divide(lastPreCountNum, 4, RoundingMode.HALF_UP);
            demandIncrease = demandIncrease.multiply(BigDecimal.valueOf(100)).setScale(2, RoundingMode.HALF_UP);
        }

        return demandIncrease;
    }

    /**
     * 已供应量
     * @param demandAndSupplyVo
     * @return
     */
    @Override
    public BigDecimal getSuppliedQuantityNum(DemandAndSupplyVo demandAndSupplyVo) {
         //已供应量
        return mainMapper.getSuppliedQuantityNum(demandAndSupplyVo);
    }

    /**
     * 供应增长量
     * @param demandAndSupplyVo
     * @return
     */
    @Override
    public BigDecimal getSuppliedQuantityIncrease(DemandAndSupplyVo demandAndSupplyVo) {
        DemandAndSupplyVo demandAndSupplyVoNew = new DemandAndSupplyVo();
        BeanUtils.copyProperties(demandAndSupplyVo,demandAndSupplyVoNew);
        // 定义日期格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        //本月以供应量
        BigDecimal suppliedQuantityNum =  this.getSuppliedQuantityNum(demandAndSupplyVoNew);
        //上个月的开始时间
        LocalDate startTime = LocalDate.parse(demandAndSupplyVo.getStartTime(), formatter);
        LocalDate lastStartTime = startTime.minusMonths(1);
        String lastStartTimeStr = lastStartTime.format(formatter);
        //上个月的结束时间
        LocalDate endTime = LocalDate.parse(demandAndSupplyVo.getEndTime(), formatter);
        LocalDate lastEndTime = endTime.minusMonths(1);
        String lastEndTimeStr = lastEndTime.format(formatter);
        //获取上个月以供应量
        demandAndSupplyVoNew.setStartTime(lastStartTimeStr);
        demandAndSupplyVoNew.setEndTime(lastEndTimeStr);
        BigDecimal lastSuppliedQuantityNum = this.getSuppliedQuantityNum(demandAndSupplyVoNew);
        //计算增长量
        BigDecimal suppliedQuantityIncrease = BigDecimal.ZERO;
        if (lastSuppliedQuantityNum.compareTo(BigDecimal.ZERO)==0 && suppliedQuantityNum.compareTo(BigDecimal.ZERO) > 0){
            suppliedQuantityIncrease = BigDecimal.valueOf(100);
        }else if (suppliedQuantityNum.compareTo(BigDecimal.ZERO)==0 && lastSuppliedQuantityNum.compareTo(BigDecimal.ZERO) > 0){
            suppliedQuantityIncrease = BigDecimal.valueOf(-100);
        } else if (lastSuppliedQuantityNum.compareTo(BigDecimal.ZERO) > 0){
            suppliedQuantityIncrease = suppliedQuantityNum.subtract(lastSuppliedQuantityNum).divide(lastSuppliedQuantityNum, 4, RoundingMode.HALF_UP);
            suppliedQuantityIncrease = suppliedQuantityIncrease.multiply(BigDecimal.valueOf(100)).setScale(2, RoundingMode.HALF_UP);
        }
        return suppliedQuantityIncrease;
    }

    /**
     * 待供应量
     * @param demandAndSupplyVo
     * @return
     */
    @Override
    public BigDecimal getSuppliedToBeQuantityNum(DemandAndSupplyVo demandAndSupplyVo) {
        //需求量
        BigDecimal preCountNum = this.getDemandNum(demandAndSupplyVo);
        //以供应量
        BigDecimal suppliedQuantityNum = this.getSuppliedQuantityNum(demandAndSupplyVo);
        //待供应量
        BigDecimal suppliedToBeQuantityNum = preCountNum.subtract(suppliedQuantityNum);

        return suppliedToBeQuantityNum;
    }

    /**
     * 待供应增长量
     * @param demandAndSupplyVo
     * @return
     */
    @Override
    public BigDecimal getSuppliedToBeQuantityIncrease(DemandAndSupplyVo demandAndSupplyVo) {
        DemandAndSupplyVo demandAndSupplyVoNew = new DemandAndSupplyVo();
        BeanUtils.copyProperties(demandAndSupplyVo,demandAndSupplyVoNew);
        //本月待供应量
        BigDecimal suppliedToBeQuantityNum = this.getSuppliedToBeQuantityNum(demandAndSupplyVoNew);
        // 定义日期格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        //上个月的开始时间
        LocalDate startTime = LocalDate.parse(demandAndSupplyVo.getStartTime(), formatter);
        LocalDate lastStartTime = startTime.minusMonths(1);
        String lastStartTimeStr = lastStartTime.format(formatter);
        //上个月的结束时间
        LocalDate endTime = LocalDate.parse(demandAndSupplyVo.getEndTime(), formatter);
        LocalDate lastEndTime = endTime.minusMonths(1);
        String lastEndTimeStr = lastEndTime.format(formatter);
        //获取上个月以供应量
        demandAndSupplyVoNew.setStartTime(lastStartTimeStr);
        demandAndSupplyVoNew.setEndTime(lastEndTimeStr);
        BigDecimal lastSuppliedToBeQuantityNum = this.getSuppliedToBeQuantityNum(demandAndSupplyVoNew);
        //计算增长量
        BigDecimal suppliedToBeQuantityIncrease = BigDecimal.ZERO;
        if (lastSuppliedToBeQuantityNum.compareTo(BigDecimal.ZERO)==0 && suppliedToBeQuantityNum.compareTo(BigDecimal.ZERO) > 0){
            suppliedToBeQuantityIncrease = BigDecimal.valueOf(100);
        }else if (suppliedToBeQuantityNum.compareTo(BigDecimal.ZERO)==0 && lastSuppliedToBeQuantityNum.compareTo(BigDecimal.ZERO) > 0){
            suppliedToBeQuantityIncrease = BigDecimal.valueOf(-100);
        }else if (lastSuppliedToBeQuantityNum.compareTo(BigDecimal.ZERO) > 0){
            suppliedToBeQuantityIncrease = suppliedToBeQuantityNum.subtract(lastSuppliedToBeQuantityNum).divide(lastSuppliedToBeQuantityNum, 4, RoundingMode.HALF_UP);
            suppliedToBeQuantityIncrease = suppliedToBeQuantityIncrease.multiply(BigDecimal.valueOf(100)).setScale(2, RoundingMode.HALF_UP);
        }
        return suppliedToBeQuantityIncrease;
    }

    /**
     * 获取未结算工程总数
     * @param demandAndSupplyVo
     * @return
     */
    @Override
    public Integer getProjectNum(DemandAndSupplyVo demandAndSupplyVo) {
        return mainMapper.getProjectNum();
    }

    /**
     * 供应总价值
     * @param demandAndSupplyVo
     * @return
     */
    @Override
    public BigDecimal getSuppliedQuantityPrice(DemandAndSupplyVo demandAndSupplyVo) {
        BigDecimal supplyPrice = BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP);
        List<DemandAndSupplyVo> list = mainMapper.getSuppliedQuantityPrice(demandAndSupplyVo);
        if (!CollectionUtils.isEmpty(list)) {
            for (DemandAndSupplyVo andSupplyVo : list) {
                supplyPrice = supplyPrice.add(andSupplyVo.getSuppliedQuantityNum().multiply(andSupplyVo.getBuyPrice()));
            }
            // 总计算结果换算为万元
            supplyPrice = supplyPrice.divide(BigDecimal.valueOf(10000), 2, RoundingMode.HALF_UP);
        }
        return supplyPrice;
    }

    /**
     * 根据时间段查询当前仓储状态详情数据
     * @param dto
     * @return
     */
    @Override
    public AjaxResult getInStockNum(MaTypeHomeVo dto) {
        // 根据时间段查询当前仓储状态详情数据
        // 获取所选当前时间数据
        MaTypeHomeVo resultVo = mainMapper.getInStockNum(dto);

        // 根据所选时间段查询上一个月的数据
        if (dto.getStartTime() != null && !dto.getStartTime().isEmpty() && dto.getEndTime() != null && !dto.getEndTime().isEmpty()) {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            try {
                LocalDate startDate = LocalDate.parse(dto.getStartTime(), formatter);
                LocalDate endDate = LocalDate.parse(dto.getEndTime(), formatter);
                // 获取上月同期开始时间
                LocalDate lastMonthStart = startDate.minusMonths(1);
                // 获取上月同期结束时间
                LocalDate lastMonthEnd = endDate.minusMonths(1);
                dto.setStartTime(lastMonthStart.format(formatter));
                dto.setEndTime(lastMonthEnd.format(formatter));
//                MaTypeHomeVo lastMonthResultVo = mainMapper.getInStockNum(dto);

                // 计算各项增长量
//                resultVo.setInStockIncrease(calculateIncrease(resultVo.getInStockNum(), lastMonthResultVo.getInStockNum()));
//                resultVo.setInUseIncrease(calculateIncrease(resultVo.getInUseNum(), lastMonthResultVo.getInUseNum()));
//                resultVo.setInRepairIncrease(calculateIncrease(resultVo.getInRepairNum(), lastMonthResultVo.getInRepairNum()));
//                resultVo.setNewPurchaseIncrease(calculateIncrease(resultVo.getNewPurchaseNum(), lastMonthResultVo.getNewPurchaseNum()));
//                resultVo.setNewRepairIncrease(calculateIncrease(resultVo.getNewRepairNum(), lastMonthResultVo.getNewRepairNum()));
            } catch (Exception e) {
                // 处理日期解析异常
                throw new RuntimeException("日期解析出错", e);
            }
        }
        return success(resultVo);
    }

    /**
     * 获取机具设备状态总数据
     * @param dto
     * @return
     */
    @Override
    public AjaxResult getMaTypeStatusTotal(MaTypeHomeVo dto) {
        BigDecimal totalNum = BigDecimal.ZERO.setScale(3, RoundingMode.HALF_UP);
        BigDecimal inStockProportion = BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP);
        BigDecimal inUseProportion = BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP);
        BigDecimal inRepairProportion = BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP);
        BigDecimal newPurchaseProportion = BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP);
        BigDecimal newRepairProportion = BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP);
        // 获取所选当前时间数据
        MaTypeHomeVo resultVo = mainMapper.getInStockNum(dto);
        if (resultVo != null) {
            totalNum = totalNum.add(resultVo.getInStockNum()).add(resultVo.getInUseNum()).add(resultVo.getInRepairNum()).add(resultVo.getNewPurchaseNum()).add(resultVo.getNewRepairNum());
            // 计算需求量百分占比，结果保留2位小数
            if (totalNum.compareTo(BigDecimal.ZERO) != 0) {
                inStockProportion = resultVo.getInStockNum().divide(totalNum, 4, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100));
                inUseProportion = resultVo.getInUseNum().divide(totalNum, 4, RoundingMode.HALF_UP)
                        .multiply(BigDecimal.valueOf(100));
                inRepairProportion = resultVo.getInRepairNum().divide(totalNum, 4, RoundingMode.HALF_UP)
                        .multiply(BigDecimal.valueOf(100));
                newPurchaseProportion = resultVo.getNewPurchaseNum().divide(totalNum, 4, RoundingMode.HALF_UP)
                        .multiply(BigDecimal.valueOf(100));
                newRepairProportion = resultVo.getNewRepairNum().divide(totalNum, 4, RoundingMode.HALF_UP)
                        .multiply(BigDecimal.valueOf(100));
            }
        }
        resultVo.setInStockProportion(inStockProportion);
        resultVo.setInUseProportion(inUseProportion);
        resultVo.setInRepairProportion(inRepairProportion);
        resultVo.setNewPurchaseProportion(newPurchaseProportion);
        resultVo.setNewRepairProportion(newRepairProportion);
        return success(resultVo);
    }

    /**
     * 计算增长量
     * @param currentNum
     * @param lastMonthNum
     * @return
     */
    private BigDecimal calculateIncrease(BigDecimal currentNum, BigDecimal lastMonthNum) {
        if (lastMonthNum.compareTo(BigDecimal.ZERO) == 0 && currentNum.compareTo(BigDecimal.ZERO) > 0) {
            return BigDecimal.valueOf(100);
        } else if (currentNum.compareTo(BigDecimal.ZERO) == 0 && lastMonthNum.compareTo(BigDecimal.ZERO) > 0) {
            return BigDecimal.valueOf(-100);
        } else if (lastMonthNum.compareTo(BigDecimal.ZERO) > 0) {
            return currentNum.subtract(lastMonthNum)
                        .divide(lastMonthNum, 4, RoundingMode.HALF_UP)
                        .multiply(BigDecimal.valueOf(100))
                        .setScale(2, RoundingMode.HALF_UP);
        }
        return BigDecimal.ZERO;
    }
    /**
     * 需求列表
     * @param demandAndSupplyVo
     * @return
     */
    @Override
    public AjaxResult getDemandList(DemandAndSupplyVo demandAndSupplyVo) {
        DemandAndSupplyVo resultVo = new DemandAndSupplyVo();
        List<String> typeNameList = new ArrayList<>();
        List<BigDecimal> demandNumList = new ArrayList<>();
        List<BigDecimal> suppliedQuantityNumList = new ArrayList<>();
        List<BigDecimal> suppliedToBeQuantityNumList = new ArrayList<>();

        // 查询列表
        List<DemandAndSupplyVo> demandList = mainMapper.getDemandList(demandAndSupplyVo);
        List<DemandAndSupplyVo> useList = mainMapper.getUseList(demandAndSupplyVo);
        List<DemandAndSupplyVo> suppliedQuantityList = mainMapper.getSuppliedQuantityList(demandAndSupplyVo);

        // 过滤 suppliedQuantityNum 为 0 的数据
        suppliedQuantityList = filterZeroSuppliedQuantity(suppliedQuantityList);

        // 合并 demandNum
        mergeDemandNum(demandList, useList);

        // 提取需求量排名前 10 的数据
        demandList = getTop10DemandList(demandList);

        // 构建结果列表
        buildResultLists(demandList, suppliedQuantityList, typeNameList, demandNumList, suppliedQuantityNumList, suppliedToBeQuantityNumList);

        // 设置结果
        resultVo.setTypeNameList(typeNameList);
        resultVo.setDemandNumList(demandNumList);
        resultVo.setSuppliedQuantityNumList(suppliedQuantityNumList);
        resultVo.setSuppliedToBeQuantityNumList(suppliedToBeQuantityNumList);

        return success(resultVo);
    }

    /**
     * 过滤数量为0的数据
     * @param suppliedQuantityList
     * @return
     */
    private static List<DemandAndSupplyVo> filterZeroSuppliedQuantity(List<DemandAndSupplyVo> suppliedQuantityList) {
        return suppliedQuantityList.stream()
                .filter(item -> item.getSuppliedQuantityNum().compareTo(BigDecimal.ZERO) != 0)
                .collect(Collectors.toList());
    }

    /**
     * 合并总需求量
     * @param demandList
     * @param useList
     */
    private static void mergeDemandNum(List<DemandAndSupplyVo> demandList, List<DemandAndSupplyVo> useList) {
        // 创建一个 Map 用于存储 typeId 对应的 DemandAndSupplyVo 对象
        Map<Long, DemandAndSupplyVo> typeIdMap = new HashMap<>();
        // 将 demandList 中的元素放入 Map 中
        for (DemandAndSupplyVo vo : demandList) {
            typeIdMap.put(vo.getTypeId(), vo);
        }
        // 遍历 useList，合并 demandNum
        for (DemandAndSupplyVo vo : useList) {
            Long typeId = vo.getTypeId();
            if (typeIdMap.containsKey(typeId)) {
                // 如果 Map 中已经存在该 typeId，则合并 demandNum
                DemandAndSupplyVo existingVo = typeIdMap.get(typeId);
                existingVo.setDemandNum(existingVo.getDemandNum().add(vo.getDemandNum()));
            } else {
                // 如果 Map 中不存在该 typeId，则将该元素添加到 Map 中
                typeIdMap.put(typeId, vo);
            }
        }
        demandList.clear();
        demandList.addAll(typeIdMap.values());
    }

    /**
     * 去总数量前10的数据
     * @param demandList
     * @return
     */
    private static List<DemandAndSupplyVo> getTop10DemandList(List<DemandAndSupplyVo> demandList) {
        return demandList.stream()
                .sorted(Comparator.comparing(DemandAndSupplyVo::getDemandNum).reversed())
                .limit(10)
                .collect(Collectors.toList());
    }

    /**
     * 构建数据
     * @param demandList
     * @param suppliedQuantityList
     * @param typeNameList
     * @param demandNumList
     * @param suppliedQuantityNumList
     * @param suppliedToBeQuantityNumList
     */
    private static void buildResultLists(List<DemandAndSupplyVo> demandList, List<DemandAndSupplyVo> suppliedQuantityList,
                                         List<String> typeNameList, List<BigDecimal> demandNumList,
                                         List<BigDecimal> suppliedQuantityNumList, List<BigDecimal> suppliedToBeQuantityNumList) {
        Map<Long, DemandAndSupplyVo> suppliedQuantityMap = suppliedQuantityList.stream()
                .collect(Collectors.toMap(DemandAndSupplyVo::getTypeId, vo -> vo, (existing, replacement) -> existing));
        for (DemandAndSupplyVo demandVo : demandList) {
            Long typeId = demandVo.getTypeId();
            if (suppliedQuantityMap.containsKey(typeId)) {
                DemandAndSupplyVo suppliedQuantityVo = suppliedQuantityMap.get(typeId);
                typeNameList.add(demandVo.getTypeName() + demandVo.getTypeModelName());
                demandNumList.add(demandVo.getDemandNum());
                suppliedQuantityNumList.add(suppliedQuantityVo.getSuppliedQuantityNum());
                suppliedToBeQuantityNumList.add(demandVo.getDemandNum().subtract(suppliedQuantityVo.getSuppliedQuantityNum()));
            } else {
                typeNameList.add(demandVo.getTypeName() + demandVo.getTypeModelName());
                demandNumList.add(demandVo.getDemandNum());
                suppliedQuantityNumList.add(BigDecimal.ZERO);
                suppliedToBeQuantityNumList.add(demandVo.getDemandNum());
            }
        }
    }
}
