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

import com.alibaba.nacos.common.utils.CollectionUtils;
import com.bonus.common.biz.config.DateTimeHelper;
import com.bonus.common.core.utils.DateUtils;
import com.bonus.common.core.utils.StringUtils;
import com.bonus.common.core.web.domain.AjaxResult;
import com.bonus.material.clz.domain.vo.MaterialRetainedEquipmentInfo;
import com.bonus.material.clz.domain.vo.lease.LeaseTotalInfo;
import com.bonus.material.push.domain.IwsCostPushBean;
import com.bonus.material.push.mapper.IwsCostPushMapper;
import com.bonus.material.push.service.IwsCostPushService;
import com.bonus.material.settlement.domain.SltAgreementInfo;
import com.bonus.material.settlement.domain.dto.PeriodCostQueryDto;
import com.bonus.material.settlement.domain.vo.PeriodCostResultVo;
import com.bonus.material.settlement.domain.vo.PeriodCostSummaryVo;
import com.bonus.material.settlement.domain.vo.SltInfoVo;
import com.bonus.material.settlement.service.ISltAgreementInfoService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author : 阮世耀
 * @version : 1.0
 * @PackagePath: com.bonus.material.push.service.impl
 * @CreateTime: 2025-01-23  14:48
 * @Description: 描述
 */
@Service
public class IwsCostPushServiceImpl implements IwsCostPushService {

    @Resource
    private IwsCostPushMapper iwsCostPushMapper;

    @Resource
    private ISltAgreementInfoService sltAgreementInfoService;


    /**
     * 根据给定的条件查找协议信息
     *
     * @param o IwsCostPushBean对象，包含查找协议所需的条件
     * @return 返回一个IwsCostPushBean列表，包含符合查找条件的协议信息
     */
    @Override
    public List<IwsCostPushBean> findAgreement(IwsCostPushBean o) {
        List<IwsCostPushBean> pushBeanList = iwsCostPushMapper.findAgreement(o);

        // 使用流式操作过滤掉null值，并设置isMatch属性
        return pushBeanList.stream()
                .filter(Objects::nonNull)
                .peek(bean -> {
                    if (StringUtils.isNotBlank(bean.getProjectId()) && StringUtils.isNotBlank(bean.getProjectCode())) {
                        bean.setIsMatch((byte) 1);
                    }
                })
                .collect(Collectors.toList());
    }

    /**
     * 查询费用推送审核数据列表
     */
    @Override
    public List<IwsCostPushBean> getCostPushCheckList(IwsCostPushBean o) {
        return iwsCostPushMapper.getCostPushCheckList(o);
    }


    /**
     * 计算月结费用
     *
     * @param costDto IwsCostPushBean对象，包含月结费用计算的所需信息
     * @return 返回一个AjaxResult对象，包含月结费用计算的结果
     */
    @Override
    public AjaxResult computeTheMonthCost(IwsCostPushBean costDto) {
        // 获取当前年月 例如:2025-01
        // todo String month = DateTimeHelper.getNowMonth();
        String month = "2025-08";
        // 获取当月第一天的日期和最后一天日期
        LocalDateTime firstDayOfMonth = getFirstDayOfMonth(month);
        LocalDateTime lastDayOfMonth = getLastDayOfMonthZ(month);
        ZoneId zone = ZoneId.systemDefault();
        // 当月第一天
        LocalDate firstDay = LocalDate.now().withDayOfMonth(1);
        // todo 测试用
        firstDay = LocalDate.of(2025, 8, 1);
        Date firstDate = Date.from(firstDay.atStartOfDay(zone).toInstant());
        // 当月最后一天
        LocalDate lastDay = LocalDate.now().withDayOfMonth(LocalDate.now().lengthOfMonth());
        // todo 测试用
        lastDay = LocalDate.of(2025, 8, 31);
        Date lastDate = Date.from(lastDay.atStartOfDay(zone).toInstant());

        // 塞入当前年月到参数中
        costDto.setMonth(month);

        // 清除旧的费用计算数据
        //cleanSameMonthOldRecords(record);

        // 插入新的当前月份,并生成记录id
        iwsCostPushMapper.insertCalcMonthRecord(costDto);

        // 查询协议信息列表
        List<IwsCostPushBean> agreementList = iwsCostPushMapper.findAgreement(costDto);
        // 过滤掉空数据
        agreementList.removeIf(Objects::isNull);

        // 处理数据,首先把已结算和未结算的协议数据分组处理
        List<IwsCostPushBean> settlementAgreementList = new ArrayList<>(); //工器具已结算协议
        List<IwsCostPushBean> safetySettlementAgreementList = new ArrayList<>(); // 安全工器具已结算协议
        List<IwsCostPushBean> unsettlementAgreementList = new ArrayList<>(); // 工器具未结算协议
        List<IwsCostPushBean> safetyUnsettlementAgreementList = new ArrayList<>(); // 安全工器具未结算协议

        // 过滤拿已结算协议列表、并且是本月结算的协议
        if (CollectionUtils.isNotEmpty(agreementList)) {
            // 工器具已结算协议
            settlementAgreementList = agreementList.stream().filter(item -> item.getSettlementTime() != null
                            && item.getIsSettlement() != null && item.getIsSettlement() == 1
                            && item.getSettlementTime().getMonth() == firstDayOfMonth.getMonth()
                            && item.getSettlementTime().getYear() == firstDayOfMonth.getYear())
                    .collect(Collectors.toList());
            // 安全🔐工器具已结算协议
            safetySettlementAgreementList = agreementList.stream().filter(item -> item.getSafetySettlementTime() != null
                            && item.getSafetyIsSettlement() != null && item.getSafetyIsSettlement() == 1
                            && item.getSafetySettlementTime().getMonth() == firstDayOfMonth.getMonth()
                            && item.getSafetySettlementTime().getYear() == firstDayOfMonth.getYear())
                    .collect(Collectors.toList());

            ///        --------过滤拿未结算协议列表------------
            // 工器具未结算协议
            unsettlementAgreementList = agreementList.stream().filter(obj -> obj.getIsSettlement() != null
                    && obj.getIsSettlement() == 0
                    && (obj.getSafetyIsSettlement() == null || obj.getSafetyIsSettlement() == 0)
            ).collect(Collectors.toList());
            // 安全🔐工器具未结算协议
            safetyUnsettlementAgreementList = agreementList.stream().filter(obj -> obj.getSafetyIsSettlement() != null
                    && obj.getSafetyIsSettlement() == 0
                    && (obj.getIsSettlement() == null || obj.getIsSettlement() == 0)
            ).collect(Collectors.toList());
        }

        /// ------------------未结算协议费用计算开始 -------------------
        // 计算未结算协议 ---- （工器具）租赁费用info列表及details明细
        List<PeriodCostSummaryVo> unsettlementEquipmentLeaseCosts = sltAgreementInfoService.selectPeriodCostSummary(new PeriodCostQueryDto()
                .setAgreementIds(unsettlementAgreementList.stream().map(IwsCostPushBean::getAgreementId).collect(Collectors.toList()))
                .setStartDate(firstDate).setEndDate(lastDate)
                .setSltManageType(1)
        );
        List<PeriodCostResultVo> unsettlementEquipmentLeaseCostsDetails = sltAgreementInfoService.selectPeriodCostList(new PeriodCostQueryDto()
                .setAgreementIds(unsettlementAgreementList.stream().map(IwsCostPushBean::getAgreementId).collect(Collectors.toList()))
                .setStartDate(firstDate).setEndDate(lastDate)
                .setSltManageType(1)
        );
        // 计算未结算协议 ---- （安全工器具）租赁费用info列表及details明细
        List<PeriodCostSummaryVo> unsettlementSafetyEquipmentLeaseCosts = sltAgreementInfoService.selectPeriodCostSummary(new PeriodCostQueryDto()
                .setAgreementIds(safetyUnsettlementAgreementList.stream().map(IwsCostPushBean::getAgreementId).collect(Collectors.toList()))
                .setStartDate(firstDate).setEndDate(lastDate)
                .setSltManageType(2)
        );
        List<PeriodCostResultVo> unsettlementSafetyEquipmentLeaseCostsDetails = sltAgreementInfoService.selectPeriodCostList(new PeriodCostQueryDto()
                .setAgreementIds(safetyUnsettlementAgreementList.stream().map(IwsCostPushBean::getAgreementId).collect(Collectors.toList()))
                .setStartDate(firstDate).setEndDate(lastDate)
                .setSltManageType(2)
        );
        /// ------------------ 未结算协议费用计算结束 --------------------


        /// ------------------------ 已经结算协议 -------------------
        List<SltAgreementInfo> settlementEquipmentCosts = new ArrayList<>();
        List<PeriodCostResultVo> settlementEquipmentCostsDetails = new ArrayList<>();
        List<SltAgreementInfo> settlementSafetyEquipmentCosts = new ArrayList<>();
        List<PeriodCostResultVo> settlementSafetyEquipmentCostsDetails = new ArrayList<>();

        if (CollectionUtils.isNotEmpty(settlementAgreementList)) {
            // 计算已结算协议 ---- （工器具）租赁、维修、丢失、报废4项费用统计📉
            settlementEquipmentCosts = sltAgreementInfoService.getSltReportedList(new SltAgreementInfo()
                    .setAgreementIds(settlementAgreementList.stream().map(IwsCostPushBean::getAgreementId).collect(Collectors.toList()))
                    .setStartTime(firstDate)
                    .setEndTime(lastDate)
                    .setSettlementType(1)
            );
            // 获取已结算协议 ---- （工器具）本月租赁的区间费用明细
            settlementEquipmentCostsDetails = sltAgreementInfoService.selectPeriodCostList(new PeriodCostQueryDto()
                    .setAgreementIds(settlementAgreementList.stream().map(IwsCostPushBean::getAgreementId).collect(Collectors.toList()))
                    .setSettlementStatus("2")
                    .setStartDate(firstDate).setEndDate(lastDate)
                    .setSltManageType(1)
            );
            // 把区间计算的租赁费用覆盖已结算的用作展示
            for (SltAgreementInfo item : settlementEquipmentCosts) {
                item.setLeaseCost(BigDecimal.ZERO);
                Long agreementId = item.getAgreementId();
                List<PeriodCostResultVo> filterArray = settlementEquipmentCostsDetails.stream().filter(obj -> obj.getAgreementId().equals(agreementId)).collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(filterArray)) {
                    filterArray.removeIf(Objects::isNull);
                    BigDecimal leaseCostFilter = BigDecimal.ZERO;
                    for (PeriodCostResultVo vo : filterArray) {
                        leaseCostFilter = leaseCostFilter.add(vo.getLeaseCost());
                    }
                    item.setLeaseCost(leaseCostFilter);
                }
            }
        }

        if (CollectionUtils.isNotEmpty(safetySettlementAgreementList)) {
            // 计算已结算协议 ---- （安全工器具）租赁、维修、丢失、报废4项费用统计📉
            settlementSafetyEquipmentCosts = sltAgreementInfoService.getSltReportedList(new SltAgreementInfo()
                    .setAgreementIds(safetySettlementAgreementList.stream().map(IwsCostPushBean::getAgreementId).collect(Collectors.toList()))
                    .setStartTime(firstDate)
                    .setEndTime(lastDate)
                    .setSettlementType(2)
            );
            // 获取已结算协议 ---- （安全工器具）的本月租赁区间费用明细
            settlementSafetyEquipmentCostsDetails = sltAgreementInfoService.selectPeriodCostList(new PeriodCostQueryDto()
                    .setAgreementIds(safetySettlementAgreementList.stream().map(IwsCostPushBean::getAgreementId).collect(Collectors.toList()))
                    .setSettlementStatus("2")
                    .setStartDate(firstDate)
                    .setEndDate(lastDate)
                    .setSltManageType(2)
            );
            // 把区间计算的租赁费用覆盖已结算的用作展示
            for (SltAgreementInfo item : settlementSafetyEquipmentCosts) {
                item.setLeaseCost(BigDecimal.ZERO);
                Long agreementId = item.getAgreementId();
                List<PeriodCostResultVo> filterArray = settlementSafetyEquipmentCostsDetails.stream().filter(obj -> obj.getAgreementId().equals(agreementId)).collect(Collectors.toList());
                filterArray.removeIf(Objects::isNull);
                BigDecimal leaseCostFilter = BigDecimal.ZERO;
                for (PeriodCostResultVo vo : filterArray) {
                    leaseCostFilter = leaseCostFilter.add(vo.getLeaseCost());
                }
                item.setLeaseCost(leaseCostFilter);
            }
        }

        /// --------------- 已经结算协议 -----------------------


        // 分别进行转换后存入数据库
        List<IwsCostPushBean> resultArray = new ArrayList<>();

        // 转化未结算工器具费用
        for (PeriodCostSummaryVo vo : unsettlementEquipmentLeaseCosts) {
            resultArray.add(new IwsCostPushBean()
                    .setAgreementId(vo.getAgreementId()).setTaskId(costDto.getTaskId()).setSettlementType((byte) 1)
                    .setLeaseMoney(vo.getTotalLeaseCost())
                    .setConsumeMoney(vo.getTotalConsumeCost())
            );
        }
        // 转化未结算安全工器具费用
        for (PeriodCostSummaryVo vo : unsettlementSafetyEquipmentLeaseCosts) {
            resultArray.add(new IwsCostPushBean()
                    .setAgreementId(vo.getAgreementId()).setTaskId(costDto.getTaskId()).setSettlementType((byte) 2)
                    .setLeaseMoney(vo.getTotalLeaseCost())
                    .setConsumeMoney(vo.getTotalConsumeCost())
            );
        }
        // 转换已结算工器具费用
        for (SltAgreementInfo vo : settlementEquipmentCosts) {
            resultArray.add(new IwsCostPushBean()
                    .setAgreementId(vo.getAgreementId()).setTaskId(costDto.getTaskId()).setSettlementType((byte) 1)
                    .setLeaseMoney(vo.getLeaseCost()).setRepairMoney(vo.getRepairCost())
                    .setLostMoney(vo.getLoseCost()).setScrapMoney(vo.getScrapCost())
                    .setConsumeMoney(vo.getConsumeCost())
            );
        }
        // 转换已结算安全工器具费用
        for (SltAgreementInfo vo : settlementSafetyEquipmentCosts) {
            resultArray.add(new IwsCostPushBean()
                    .setAgreementId(vo.getAgreementId()).setTaskId(costDto.getTaskId()).setSettlementType((byte) 2)
                    .setLeaseMoney(vo.getLeaseCost()).setRepairMoney(vo.getRepairCost())
                    .setLostMoney(vo.getLoseCost()).setScrapMoney(vo.getScrapCost())
                    .setConsumeMoney(vo.getConsumeCost())
            );
        }

        // 批量插入 -- 存入数据库costs列表
        int addProjectMonthCostsMapperResult = iwsCostPushMapper.insertProjectMonthCosts(resultArray);
        // 批量插入 -- 存入数据库租赁费用明细（project_month_info表）
        if (CollectionUtils.isNotEmpty(unsettlementEquipmentLeaseCostsDetails)) {
            // （工器具）未结算租赁费用的存入
            unsettlementEquipmentLeaseCostsDetails.forEach(item -> {
                item.setTaskId(costDto.getTaskId());
                item.setEquipmentType((byte) 1);
            });
            iwsCostPushMapper.insertProjectMonthCostsDetails(unsettlementEquipmentLeaseCostsDetails);
        }
        if (CollectionUtils.isNotEmpty(settlementEquipmentCostsDetails)) {
            // （工器具）已结算租赁费用的存入
            settlementEquipmentCostsDetails.forEach(item -> {
                item.setTaskId(costDto.getTaskId());
                item.setEquipmentType((byte) 1);
            });
            iwsCostPushMapper.insertProjectMonthCostsDetails(settlementEquipmentCostsDetails);
        }
        if (CollectionUtils.isNotEmpty(unsettlementSafetyEquipmentLeaseCostsDetails)) {
            // （安全工器具）未结算租赁费用的存入
            unsettlementSafetyEquipmentLeaseCostsDetails.forEach(item -> {
                item.setTaskId(costDto.getTaskId());
                item.setEquipmentType((byte) 2);
            });
            iwsCostPushMapper.insertProjectMonthCostsDetails(unsettlementSafetyEquipmentLeaseCostsDetails);
        }
        if (CollectionUtils.isNotEmpty(settlementSafetyEquipmentCostsDetails)) {
            // （安全工器具）已结算租赁费用的存入
            settlementSafetyEquipmentCostsDetails.forEach(item -> {
                item.setTaskId(costDto.getTaskId());
                item.setEquipmentType((byte) 2);
            });
            iwsCostPushMapper.insertProjectMonthCostsDetails(settlementSafetyEquipmentCostsDetails);
        }

        return 0 < addProjectMonthCostsMapperResult ? AjaxResult.success("月结费用计算成功") : AjaxResult.error("月结费用计算失败");
    }

    /**
     * 根据协议ID及月份查询当月租赁费用明细
     *
     * @param record 传入查询的年月：yyyy-MM 及 协议ID
     */
    @Override
    public List<IwsCostPushBean> getLeaseCostsByAgreementIdAndMonth(IwsCostPushBean record) {
        if (Objects.isNull(record) || Objects.isNull(record.getMonth()) || Objects.isNull(record.getAgreementId())) {
            System.err.println("查询信息为空 = " + record);
            return Collections.emptyList();
        }

        // 获取前端传入年月对应的第一天与最后一天 LocalDateTime对象
        //LocalDateTime queryStartTime = getFirstDayOfMonth(record.getMonth());
        //LocalDateTime queryEndTime = getLastDayOfMonthZ(record.getMonth());

        //List<IwsCostPushBean> theMonthAgreementLeaseList = iwsCostPushMapper.getPaidSltBaseInfo(record);
        List<IwsCostPushBean> theMonthAgreementLeaseList = iwsCostPushMapper.getLeaseCostsByAgreementIdAndMonth(record);
        if (CollectionUtils.isEmpty(theMonthAgreementLeaseList)) {
            return Collections.emptyList();
        } else {
            // 过滤异常数据
            theMonthAgreementLeaseList.removeIf(item ->
                    Objects.isNull(item) ||
                    Objects.isNull(item.getTypeId()) ||
                    Objects.isNull(item.getLeaseNum()) ||
                    Objects.isNull(item.getLeasePrice())
            );
//            for (IwsCostPushBean leaseCostInfo : theMonthAgreementLeaseList) {
//                if (null == leaseCostInfo.getLeaseDate()) { continue; }
//                if (null == leaseCostInfo.getBackDate()) { leaseCostInfo.setBackDate(queryEndTime); }
//
//                // 校准计算后的日期
//                if (leaseCostInfo.getLeaseDate().isBefore(queryStartTime)) {
//                    leaseCostInfo.setLeaseDate(queryStartTime);
//                } else if (leaseCostInfo.getLeaseDate().isAfter(queryEndTime)) {
//                    leaseCostInfo.setLeaseDays(0);
//                    leaseCostInfo.setDelFlag(true);
//                    continue;
//                }
//                if (leaseCostInfo.getBackDate().isAfter(queryEndTime)) {
//                    leaseCostInfo.setBackDate(queryEndTime);
//                } else if (leaseCostInfo.getBackDate().isBefore(queryStartTime)) {
//                    leaseCostInfo.setLeaseDays(0);
//                    leaseCostInfo.setDelFlag(true);
//                    continue;
//                }
//
//                // 计算天数
//                leaseCostInfo.setLeaseDays(Math.toIntExact(calculateDaysInclusive(leaseCostInfo.getLeaseDate(), leaseCostInfo.getBackDate())));
//                // 计算费用
//                leaseCostInfo.setLeaseMoney(new BigDecimal(leaseCostInfo.getLeaseDays())
//                        .multiply(leaseCostInfo.getLeasePrice())
//                        .multiply(leaseCostInfo.getLeaseNum()).setScale(2, RoundingMode.HALF_UP)
//                );
//
//            }

            // 删除标记的非期间段数据
            // theMonthAgreementLeaseList.removeIf(IwsCostPushBean::isDelFlag);
            return theMonthAgreementLeaseList;
        }
    }

    /**
     * 计算月结费用详情
     * @param agreementList 协议集合
     * @param firstDay 月份第一天
     * @param lastDay 月份最后一天
     */
    private void computeMonthInfoDetail(List<IwsCostPushBean> agreementList, String month, LocalDateTime firstDay, LocalDateTime lastDay) {
        if (null == agreementList || agreementList.isEmpty()) {
            System.err.println("---------agreementList为空----------");
        } else {
            System.out.println("agreementList数据不为空");

            // 过滤异常数据
            agreementList.removeIf(item ->
                            Objects.isNull(item) ||
                            Objects.isNull(item.getAgreementId()) ||
                            Objects.isNull(item.getSignTime()) ||
                            Objects.isNull(item.getIsSettlement()) ||
                            item.getSignTime().isAfter(lastDay) || item.getSettlementTime().isBefore(firstDay)
            );

            for (IwsCostPushBean agreement : agreementList) {
                // 协议id
                Long agreementId = agreement.getAgreementId();
                // 更新协议推送状态
                updatePushStatus(agreement);

                // 对已结算、未结算分开处理
                if (0 == agreement.getIsSettlement()) {
                    // 未结算时，无丢失、维修、报废费用
                    agreement.setLostMoney(BigDecimal.ZERO);
                    agreement.setRepairMoney(BigDecimal.ZERO);
                    agreement.setScrapMoney(BigDecimal.ZERO);

                    // 查询领料费用
                    List<IwsCostPushBean> leaseCostsByAgreementIdAndMonth = this.getLeaseCostsByAgreementIdAndMonth(new IwsCostPushBean()
                            .setAgreementId(agreementId)
                            .setMonth(month)
                    );
                    if (CollectionUtils.isEmpty(leaseCostsByAgreementIdAndMonth)) {
                        agreement.setLeaseMoney(BigDecimal.ZERO);
                    } else {
                        leaseCostsByAgreementIdAndMonth.removeIf(item -> Objects.isNull(item) || Objects.isNull(item.getLeaseMoney()));
                        // 合并计算领料费用
                        agreement.setLeaseMoney(leaseCostsByAgreementIdAndMonth
                                .stream()
                                .map(IwsCostPushBean::getLeaseMoney)
                                .reduce(BigDecimal.ZERO, BigDecimal::add)
                        );
                    }
                } else if (1 == agreement.getIsSettlement()) {
                    // 已结算费用计算
                    SltInfoVo sltServiceResult = sltAgreementInfoService.getSltInfo(new SltAgreementInfo().setAgreementId(Long.valueOf(agreementId)));
                    if (Objects.isNull(sltServiceResult)) {
                        System.err.println("sltServiceResult为空----null");
                        agreement.setLostMoney(BigDecimal.ZERO);
                        agreement.setRepairMoney(BigDecimal.ZERO);
                        agreement.setScrapMoney(BigDecimal.ZERO);
                        agreement.setLeaseMoney(BigDecimal.ZERO);
                    } else {
                        // 已经结算时，要统计领料、丢失、维修、报废费用
                        agreement.setLostMoney(Optional.ofNullable(sltServiceResult.getLoseCost()).orElse(BigDecimal.ZERO));
                        agreement.setRepairMoney(Optional.ofNullable(sltServiceResult.getRepairCost()).orElse(BigDecimal.ZERO));
                        agreement.setScrapMoney(Optional.ofNullable(sltServiceResult.getScrapCost()).orElse(BigDecimal.ZERO));
                        agreement.setLeaseMoney(Optional.ofNullable(sltServiceResult.getLeaseCost()).orElse(BigDecimal.ZERO));
                    }
                }

                // 合并统计费用
                agreement.setTotalMoney(agreement.getLeaseMoney()
                        .add(agreement.getLostMoney())
                        .add(agreement.getRepairMoney())
                        .add(agreement.getScrapMoney())
                );
            }
        }
    }


    /**
     * 更新协议推送状态
     *
     * @param bean IwsCostPushBean对象，包含推送状态更新的信息
     */
    private void updatePushStatus(IwsCostPushBean bean) {
        String isPush = checkPush(bean) ? "0" : "1";
        bean.setIsPush(isPush);
        iwsCostPushMapper.updateAgreementIsPush(bean);
    }

    /**
     * 检查是否包含大件及机械化，项目id为空的
     * return true 包含大件、机械化 或 工程id为空,  false 不包含
     */
    private boolean checkPush(IwsCostPushBean o) {
        return (o.getUnitName().contains("大件") || o.getUnitName().contains("机械化") || StringUtils.isEmpty(o.getProjectId()));
    }

    /**
     * 根据字符串形式的年月获取当月的第一天
     *
     * @param yearMonth 字符串形式的年月，格式为 "yyyy-MM" 例如 2024-09
     * @return 当月的第一天的 LocalDateTime 对象，时间部分为 00:00:00
     */
    public static LocalDateTime getFirstDayOfMonth(String yearMonth) {
        // 解析字符串为 LocalDate
        LocalDate date = LocalDate.parse(yearMonth + "-01", DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        // 获取当月的第一天
        LocalDate firstDay = date.with(TemporalAdjusters.firstDayOfMonth());
        // 转换为 LocalDateTime，时间部分为 00:00:00
        return firstDay.atStartOfDay();
    }

    /**
     * 根据字符串形式的年月获取当月的最后一天
     *
     * @param yearMonth 字符串形式的年月，格式为 "yyyy-MM" 例如 2024-09
     * @return 当月的最后一天的 LocalDateTime 对象，时间部分为 23:59:59
     */
    public static LocalDateTime getLastDayOfMonthZ(String yearMonth) {
        // 解析字符串为 LocalDate
        LocalDate date = LocalDate.parse(yearMonth + "-01", DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        // 获取当月的最后一天
        LocalDate lastDay = date.with(TemporalAdjusters.lastDayOfMonth());
        // 转换为 LocalDateTime，时间部分为 23:59:59
        return lastDay.atTime(23, 59, 59);
    }

    /**
     * 计算两个 LocalDateTime 之间的天数（当天开始和当天结束的情况也算1天）
     *
     * @param start 开始时间
     * @param end   结束时间
     * @return 天数差（包括当天）
     */
    public static long calculateDaysInclusive(LocalDateTime start, LocalDateTime end) {
        // 如果结束时间早于开始时间，交换两者
        if (end.isBefore(start)) {
            LocalDateTime temp = start;
            start = end;
            end = temp;
        }
        // 计算完整天数差
        long daysBetween = ChronoUnit.DAYS.between(start.toLocalDate(), end.toLocalDate());
        // 如果结束时间的时间部分晚于或等于开始时间的时间部分，则加 1 天
        if (!end.toLocalTime().isBefore(start.toLocalTime())) {daysBetween += 1;}

        return daysBetween;
    }

    /**
     * @author jsk
     *根据工程查询领用信息
     */
    @Override
    public List<IwsCostPushBean> getProLeaseInfo(IwsCostPushBean info) {
        List<IwsCostPushBean> list=new ArrayList<>();
        try{
            BigDecimal preNum = BigDecimal.ZERO.setScale(3, RoundingMode.HALF_UP);
            BigDecimal outNum = BigDecimal.ZERO.setScale(3, RoundingMode.HALF_UP);
            BigDecimal pendingNum = BigDecimal.ZERO.setScale(3, RoundingMode.HALF_UP);
            info.setProjectId(String.join(",", info.getProjectIds()));
            list=iwsCostPushMapper.getProLeaseInfo(info);
            if (!org.springframework.util.CollectionUtils.isEmpty(list)) {
                for (IwsCostPushBean leaseTotalInfo : list) {
                    // 根据typeId和parentId查询领料数量
                    IwsCostPushBean totalInfo = iwsCostPushMapper.getTotalInfo(leaseTotalInfo);
                    if (totalInfo != null) {
                        leaseTotalInfo.setPreNum(totalInfo.getPreNum());
                        leaseTotalInfo.setPendingNum(leaseTotalInfo.getPreNum().subtract(leaseTotalInfo.getOutNum()));
                    }
                    preNum = preNum.add(leaseTotalInfo.getPreNum());
                    outNum = outNum.add(leaseTotalInfo.getOutNum());
                    pendingNum = pendingNum.add(leaseTotalInfo.getPendingNum());
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return list;
    }

    /**
     * 根据机具类型查询机具列表接口
     * @param bean
     * @return
     */
    @Override
    public List<MaterialRetainedEquipmentInfo> getEquipmentListByType(IwsCostPushBean bean) {
        BigDecimal totalPrice = BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP);
        BigDecimal totalStoreNum = BigDecimal.ZERO.setScale(3, RoundingMode.HALF_UP);
        BigDecimal totalUsNum = BigDecimal.ZERO.setScale(3, RoundingMode.HALF_UP);
        BigDecimal totalRepairNum = BigDecimal.ZERO.setScale(3, RoundingMode.HALF_UP);
        BigDecimal totalInputNum = BigDecimal.ZERO.setScale(3, RoundingMode.HALF_UP);
        BigDecimal totalRepairInputNum = BigDecimal.ZERO.setScale(3, RoundingMode.HALF_UP);
        BigDecimal totalAllNum = BigDecimal.ZERO.setScale(3, RoundingMode.HALF_UP);
        try{
            bean.setProjectId(String.join(",", bean.getProjectIds()));
        }catch (Exception e){}
        List<MaterialRetainedEquipmentInfo> recordList = iwsCostPushMapper.getEquipmentListByType(bean);
        if (CollectionUtils.isNotEmpty(recordList)) {
            for (MaterialRetainedEquipmentInfo retainedEquipmentInfo : recordList) {
                totalStoreNum = totalStoreNum.add(retainedEquipmentInfo.getStoreNum());
                totalUsNum = totalUsNum.add(retainedEquipmentInfo.getUsNum());
                totalAllNum = totalAllNum.add(retainedEquipmentInfo.getAllNum());
                BigDecimal equipmentPrice = retainedEquipmentInfo.getAllNum()
                        .multiply(retainedEquipmentInfo.getBuyPrice())
                        .divide(new BigDecimal(10000), 2, RoundingMode.HALF_UP);
                totalPrice = totalPrice.add(equipmentPrice);
                retainedEquipmentInfo.setTotalPrice(equipmentPrice);
            }
        }
        return recordList;
    }

    /**
     * 根据工程/往来单位/协议号查询机具信息
     * @param bean
     * @return
     */
    @Override
    public List<MaterialRetainedEquipmentInfo> getEquipmentListByAgreementCode(IwsCostPushBean bean) {
        BigDecimal totalPrice = BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP);
        BigDecimal totalStoreNum = BigDecimal.ZERO.setScale(3, RoundingMode.HALF_UP);
        BigDecimal totalUsNum = BigDecimal.ZERO.setScale(3, RoundingMode.HALF_UP);
        BigDecimal totalRepairNum = BigDecimal.ZERO.setScale(3, RoundingMode.HALF_UP);
        BigDecimal totalInputNum = BigDecimal.ZERO.setScale(3, RoundingMode.HALF_UP);
        BigDecimal totalRepairInputNum = BigDecimal.ZERO.setScale(3, RoundingMode.HALF_UP);
        BigDecimal totalAllNum = BigDecimal.ZERO.setScale(3, RoundingMode.HALF_UP);
        try{
            bean.setProjectId(String.join(",", bean.getProjectIds()));
        }catch (Exception e){}
        List<MaterialRetainedEquipmentInfo> recordList = iwsCostPushMapper.getEquipmentListByAgreementCode(bean);
        if (CollectionUtils.isNotEmpty(recordList)) {
            for (MaterialRetainedEquipmentInfo retainedEquipmentInfo : recordList) {
                totalStoreNum = totalStoreNum.add(retainedEquipmentInfo.getStoreNum());
                totalUsNum = totalUsNum.add(retainedEquipmentInfo.getUsNum());
                totalAllNum = totalAllNum.add(retainedEquipmentInfo.getAllNum());
                BigDecimal equipmentPrice = retainedEquipmentInfo.getAllNum()
                        .multiply(retainedEquipmentInfo.getBuyPrice())
                        .divide(new BigDecimal(10000), 2, RoundingMode.HALF_UP);
                totalPrice = totalPrice.add(equipmentPrice);
                retainedEquipmentInfo.setTotalPrice(equipmentPrice);
            }
        }
        return recordList;
    }
}
