package cn.iocoder.yudao.module.system.service.holiday.holidaysetting;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.map.MapUtil;
import cn.iocoder.yudao.framework.common.Constants;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils;
import cn.iocoder.yudao.module.system.controller.admin.holiday.holidaybalancesetting.vo.HolidayBalanceSettingRespVO;
import cn.iocoder.yudao.module.system.controller.admin.holiday.holidaysetting.dto.RecalculateAssignedDTO;
import cn.iocoder.yudao.module.system.controller.admin.holiday.holidaysetting.vo.*;
import cn.iocoder.yudao.module.system.controller.admin.holiday.holidaysettingrange.vo.HolidaySettingRangeRespVO;
import cn.iocoder.yudao.module.system.controller.admin.holiday.holidaysettingrange.vo.HolidaySettingRangeSaveReqVO;
import cn.iocoder.yudao.module.system.controller.admin.holiday.holidayworkingage.vo.HolidayWorkingAgeRespVO;
import cn.iocoder.yudao.module.system.dal.dataobject.holiday.holidaybalancesetting.HolidayBalanceSettingDO;
import cn.iocoder.yudao.module.system.dal.dataobject.holiday.holidaysetting.HolidaySettingDO;
import cn.iocoder.yudao.module.system.dal.dataobject.holiday.holidaysettingrange.HolidaySettingRangeDO;
import cn.iocoder.yudao.module.system.dal.dataobject.holiday.holidayuser.HolidayUserDO;
import cn.iocoder.yudao.module.system.dal.dataobject.holiday.holidayworkingage.HolidayWorkingAgeDO;
import cn.iocoder.yudao.module.system.dal.dataobject.laborcontract.LaborContractDO;
import cn.iocoder.yudao.module.system.dal.mysql.holiday.holidaybalancesetting.HolidayBalanceSettingMapper;
import cn.iocoder.yudao.module.system.dal.mysql.holiday.holidaysetting.HolidaySettingMapper;
import cn.iocoder.yudao.module.system.dal.mysql.holiday.holidaysettingrange.HolidaySettingRangeMapper;
import cn.iocoder.yudao.module.system.dal.mysql.holiday.holidayuser.HolidayUserMapper;
import cn.iocoder.yudao.module.system.dal.mysql.holiday.holidayworkingage.HolidayWorkingAgeMapper;
import cn.iocoder.yudao.module.system.service.holiday.holidaybalancesetting.HolidayBalanceSettingService;
import cn.iocoder.yudao.module.system.service.holiday.holidaysettingrange.HolidaySettingRangeService;
import cn.iocoder.yudao.module.system.service.holiday.holidayuserrecord.HolidayUserRecordService;
import cn.iocoder.yudao.module.system.service.holiday.holidayworkingage.HolidayWorkingAgeService;
import cn.iocoder.yudao.module.system.service.laborcontract.LaborContractService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.Month;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.THE_LEAVE_PROCESS_CANNOT_BE_USED_WITHOUT_SIGNING_THE_CONTRACT;

/**
 * 假期设置 Service 实现类
 *
 * @author 艾楷
 */
@Service
@Validated
@Slf4j
public class HolidaySettingServiceImpl implements HolidaySettingService {

    @Resource
    private HolidaySettingMapper holidaySettingMapper;
    @Resource
    private HolidayBalanceSettingMapper holidayBalanceSettingMapper;
    @Resource
    private HolidayBalanceSettingService holidayBalanceSettingService;
    @Resource
    private HolidaySettingRangeMapper holidaySettingRangeMapper;
    @Resource
    private HolidaySettingRangeService holidaySettingRangeService;
    @Resource
    private HolidayWorkingAgeMapper holidayWorkingAgeMapper;
    @Resource
    private HolidayWorkingAgeService holidayWorkingAgeService;
    @Resource
    private HolidayUserRecordService holidayUserRecordService;
    @Resource
    private HolidayUserMapper holidayUserMapper;
    @Resource
    private LaborContractService laborContractService;

    @Override
    public Long createHolidaySetting(HolidaySettingSaveReqVO createReqVO) {
        // 插入
        HolidaySettingDO holidaySetting = BeanUtils.toBean(createReqVO, HolidaySettingDO.class);
        holidaySettingMapper.insert(holidaySetting);
        // 返回
        return holidaySetting.getId();
    }

    @Override
    public void updateHolidaySetting(HolidaySettingSaveReqVO updateReqVO) {
        // 更新
        HolidaySettingDO updateObj = BeanUtils.toBean(updateReqVO, HolidaySettingDO.class);
        holidaySettingMapper.updateById(updateObj);
    }

    @Override
    public void deleteHolidaySetting(Long id) {
        // 删除
        holidaySettingMapper.deleteById(id);
    }

    @Override
    public HolidaySettingDO getHolidaySetting(Long id) {
        HolidaySettingDO holidaySettingDO = holidaySettingMapper.selectById(id);
        HolidayBalanceSettingDO holidayBalanceSettingDO = holidayBalanceSettingService.selectBySettingId(id);
        holidaySettingDO.setHolidayBalanceSettingDO(holidayBalanceSettingDO);
        return holidaySettingDO;
    }

    @Override
    public PageResult<HolidaySettingDO> getHolidaySettingPage(HolidaySettingPageReqVO pageReqVO) {
        IPage<HolidaySettingDO> assetsDOIPage = holidaySettingMapper.getHolidaySettingPage(pageReqVO, MyBatisUtils.buildPage(pageReqVO));
        return new PageResult<>(assetsDOIPage.getRecords(), assetsDOIPage.getTotal());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createOrEdit(HolidaySettingSaveReqVO createReqVO) {
        //假期设置
        HolidaySettingDO holidaySetting = BeanUtils.toBean(createReqVO, HolidaySettingDO.class);
        //假期余额设置
        HolidayBalanceSettingDO holidayBalanceSetting = createReqVO.getHolidayBalanceSettingSaveReqVO() == null ? new HolidayBalanceSettingDO().init(holidaySetting.getId())
                : BeanUtils.toBean(createReqVO.getHolidayBalanceSettingSaveReqVO().setHolidaySettingId(holidaySetting.getId()), HolidayBalanceSettingDO.class);
        //假期额度工龄配置
        List<HolidayWorkingAgeDO> holidayWorkingAges = new ArrayList<>();
        if (createReqVO.getHolidayBalanceSettingSaveReqVO() != null &&
                CollectionUtil.isNotEmpty(createReqVO.getHolidayBalanceSettingSaveReqVO().getHolidayWorkingAgeSaveReqVOS())) {
            holidayWorkingAges = BeanUtils.toBean(createReqVO.getHolidayBalanceSettingSaveReqVO().getHolidayWorkingAgeSaveReqVOS(), HolidayWorkingAgeDO.class);
        }
        //假期规则人员范围
        List<HolidaySettingRangeDO> holidaySettingRanges = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(createReqVO.getHolidaySettingRangeSaveReqVOS())) {
            List<HolidaySettingRangeSaveReqVO> holidaySettingRangeSaveReqVOS = createReqVO.getHolidaySettingRangeSaveReqVOS();
            holidaySettingRanges = BeanUtils.toBean(holidaySettingRangeSaveReqVOS, HolidaySettingRangeDO.class);
        }

        if (holidaySetting.getId() == null) {
            this.batchSave(holidaySetting, holidayBalanceSetting, holidaySettingRanges, holidayWorkingAges);
            return holidaySetting.getId();
        }

        this.batchEdit(holidaySetting, holidayBalanceSetting, holidaySettingRanges, holidayWorkingAges);
        return holidaySetting.getId();
    }

    @Override
    public HolidaySettingRespVO getHolidaySettingRespVO(Long id) {
        HolidaySettingDO holidaySettingDO = holidaySettingMapper.selectById(id);
        HolidaySettingRespVO respVO = BeanUtils.toBean(holidaySettingDO, HolidaySettingRespVO.class);
        List<HolidaySettingRangeDO> holidaySettingRangeDOS = holidaySettingRangeService.selectBySettingId(id);
        List<HolidaySettingRangeRespVO> holidaySettingRangeRespVOS = BeanUtils.toBean(holidaySettingRangeDOS, HolidaySettingRangeRespVO.class);
        HolidayBalanceSettingDO holidayBalanceSettingDO = holidayBalanceSettingService.getHolidayBalanceSetting(id);
        HolidayBalanceSettingRespVO holidayBalanceSettingRespVO = BeanUtils.toBean(holidayBalanceSettingDO, HolidayBalanceSettingRespVO.class);
        List<HolidayWorkingAgeDO> holidayWorkingAgeDOS = holidayWorkingAgeService.selectBySettingId(id);
        List<HolidayWorkingAgeRespVO> holidayWorkingAgeRespVOS = BeanUtils.toBean(holidayWorkingAgeDOS, HolidayWorkingAgeRespVO.class);
        respVO.setHolidaySettingRangeRespVOS(holidaySettingRangeRespVOS);
        respVO.setHolidayBalanceSettingRespVO(holidayBalanceSettingRespVO);
        if (holidayBalanceSettingRespVO != null) {
            holidayBalanceSettingRespVO.setHolidayWorkingAgeRespVOS(holidayWorkingAgeRespVOS);
        }
        return respVO;
    }

    // TODO: 2024/11/7 编辑的时候 没有发放当月 - 新增的时候没有历史
    private void batchSave(HolidaySettingDO holidaySetting, HolidayBalanceSettingDO holidayBalanceSetting, List<HolidaySettingRangeDO> holidaySettingRanges, List<HolidayWorkingAgeDO> holidayWorkingAges) {
        // ------- 插入假期设置
        holidaySettingMapper.insert(holidaySetting);
        // -- 如果人员范围不为空的话
        if (CollectionUtil.isNotEmpty(holidaySettingRanges)) {
            holidaySettingRanges.forEach(holidaySettingRangeDO -> holidaySettingRangeDO.setHolidaySettingId(holidaySetting.getId()));
            // ---------- 插入假期规则人员范围
            holidaySettingRangeMapper.insertBatch(holidaySettingRanges);
        }
        //本次发放时间 要不要加上？- 不然的话我都不知道什么时候发放下一次怎么办呢？

        // ---------- 插入假期余额设置 如果没有的话初始化一个关闭的对象
        LocalDateTime issueTime = this.calculateNextReleaseDate(LocalDateTime.now(), holidayBalanceSetting);
        holidayBalanceSetting.setHolidaySettingId(holidaySetting.getId());
        holidayBalanceSetting.setIssueTime(issueTime);
        holidayBalanceSettingMapper.insert(holidayBalanceSetting);

        // --------------- 插入 假期额度工龄配置
        if (CollectionUtil.isNotEmpty(holidayWorkingAges)) {
            holidayWorkingAges.forEach(vo -> {
                vo.setHolidaySettingId(holidaySetting.getId());
                vo.setHolidayBalanceSettingId(holidayBalanceSetting.getId());
            });
            holidayWorkingAgeMapper.insertBatch(holidayWorkingAges);
        }
        // -- 计算假期
        if (holidayBalanceSetting.getStatus() == 1) {
            holidayUserRecordService.init(holidaySetting, holidaySettingRanges, holidayBalanceSetting, holidayWorkingAges);
        }
    }

    /**
     * 计算下一次发放日期
     *
     * @param now
     * @param holidayBalanceSetting
     * @return
     */
    @Override
    public LocalDateTime calculateNextReleaseDate(LocalDateTime now, HolidayBalanceSettingDO holidayBalanceSetting) {
        LocalDateTime issueTime = null;
        if (holidayBalanceSetting.getType() == 1) {
            //获取下个月几号
            //判断是否大于当前时间 - 如果是的话则已经有发放
            LocalDateTime localDateTime = now.withDayOfMonth(holidayBalanceSetting.getIssueTimeType());
            if (now.isBefore(localDateTime)) {
                issueTime = localDateTime;
            } else {
                issueTime = localDateTime.plusMonths(1);
            }
        } else if (holidayBalanceSetting.getType() == 2) {
            if (holidayBalanceSetting.getIssueTimeType() == 2) {
                //获取明年1月1号
                LocalDateTime localDateTime = now.withMonth(Month.JANUARY.getValue()).withDayOfMonth(1);
                if (now.isBefore(localDateTime)) {
                    issueTime = localDateTime;
                } else {
                    issueTime = localDateTime.plusYears(1);
                }
            }
        }
        // -- 取一天的开始时间
        if (issueTime != null) {
            issueTime = LocalDateTimeUtil.beginOfDay(issueTime);
        }
        return issueTime;
    }

    @Override
    public List<HolidaySettingDO> getAll() {
        return holidaySettingMapper.selectList();
    }

    @Override
    public List<HolidaySettingRespVO> getAllHolidaySetting(Long userId) {
        List<HolidaySettingDO> allList = this.getAll();
        List<HolidayUserDO> items = holidayUserMapper.selectList(new LambdaQueryWrapper<HolidayUserDO>().eq(HolidayUserDO::getUserId, userId));
        Map<Long, HolidayUserDO> HolidayUserMap = MapUtil.empty();
        if (CollUtil.isNotEmpty(items)) {
            HolidayUserMap = items.stream().collect(Collectors.toMap(HolidayUserDO::getHolidayBalanceSettingId, holidayUserDO -> holidayUserDO));
        }
        List<HolidaySettingRespVO> list = new ArrayList<>();
        List<HolidaySettingRespVO> vos = BeanUtils.toBean(allList, HolidaySettingRespVO.class);
        List<HolidayBalanceSettingDO> holidayBalanceSettingDOS = holidayBalanceSettingService.getHolidayBalanceSettingByHolidaySettingIds(allList.stream().map(HolidaySettingDO::getId).collect(Collectors.toList()));
        List<HolidayBalanceSettingRespVO> holidayBalanceSettingRespVOS = BeanUtils.toBean(holidayBalanceSettingDOS, HolidayBalanceSettingRespVO.class);
        Map<Long, HolidayBalanceSettingRespVO> holidayBalanceSettingRespVOMap = holidayBalanceSettingRespVOS.stream().collect(Collectors.toMap(HolidayBalanceSettingRespVO::getHolidaySettingId, Function.identity()));
        //获取当前登录用户最早的合同 - 获取到
        LaborContractDO laborContractDO = laborContractService.getTheEarliestContract(userId);
        if (laborContractDO == null) {
            throw exception(THE_LEAVE_PROCESS_CANNOT_BE_USED_WITHOUT_SIGNING_THE_CONTRACT);
        }
        for (HolidaySettingRespVO vo : vos) {
            HolidayBalanceSettingRespVO holidayBalanceSettingRespVO = holidayBalanceSettingRespVOMap.get(vo.getId());
            HolidayUserDO holidayUserDO = HolidayUserMap.get(vo.getId());
            // -- 如果是转正后才可以请假 - 判断用户是否已经转正 - 如果未转正则过滤掉
            if (vo.getNewEmployeeLeaveType() == 2) {
                LocalDateTime becomeARegularWorkerTime = laborContractDO.getSigningDate().atStartOfDay().plusMonths(laborContractDO.getProbationPeriodTime() == null ? 0 : laborContractDO.getProbationPeriodTime());
                if (LocalDateTime.now().isBefore(becomeARegularWorkerTime)) {
                    continue;
                }
            }
            // -- 过滤掉不适用的
            if ((holidayBalanceSettingRespVO != null && holidayBalanceSettingRespVO.getStatus() == 1) && holidayUserDO == null) {
                continue;
            } else {
                vo.setHolidayBalance(holidayUserDO == null ? null : holidayUserDO.getHolidayBalance());
            }
            vo.setHolidayBalanceSettingRespVO(holidayBalanceSettingRespVOMap.get(vo.getId()));
            list.add(vo);
        }
        return list;
    }

    @Override
    public List<HolidaySettingDO> listByIds(List<Long> holidaySettingIds) {
        if (CollectionUtil.isEmpty(holidaySettingIds)) {
            return Collections.emptyList();
        }
        return holidaySettingMapper.selectBatchIds(holidaySettingIds);
    }

    @Override
    public List<HolidaySettingDO> getLimitBalanceHolidayList() {
        return holidaySettingMapper.getLimitBalanceHolidayList();
    }

    @Override
    public List<HolidaySettingDO> getHolidaySettingByIds(List<Long> holidaySettingIds) {
        List<HolidaySettingDO> holidaySettingDOS = holidaySettingMapper.selectBatchIds(holidaySettingIds);
        Map<Long, HolidayBalanceSettingDO> map = holidayBalanceSettingService.selectBySettingIds(holidaySettingIds);
        for (HolidaySettingDO holidaySettingDO : holidaySettingDOS) {
            holidaySettingDO.setHolidayBalanceSettingDO(map.get(holidaySettingDO.getId()));
        }
        return holidaySettingDOS;
    }


    /**
     * 编辑假期设置
     * 让我们来捋一下逻辑 - 这里有下面4个情况要处理
     * 1.假期余额设置 开关 （需要清空所有相关人员的假期余额）
     * 2.人员变动 （需要清空多余人员的请假额度）
     * 3.假期发放方式调整 历史余额将会被清空 按新的方式重新发送
     * 4.发放日期调整 修改发放日期后假期余额将按新规则重新计算 - 计算规则：历史请假记录扣减当前年度余额，例如：把发放日期从2019年1月1日1改到2019年6月1日；之前在1月1日和6月1日之间的请假记录也算在2019年的请假额度里。
     * 5.更改额度配置规则 修改余额发放方式后，假期余额将按新规则重新发放。
     */

    private void batchEdit(HolidaySettingDO holidaySetting, HolidayBalanceSettingDO holidayBalanceSetting, List<HolidaySettingRangeDO> holidaySettingRanges, List<HolidayWorkingAgeDO> holidayWorkingAges) {
        // -- 更新假期设置
        holidaySettingMapper.updateById(holidaySetting);
        // -- 更新假期余额设置
        HolidayBalanceSettingDO oldHolidayBalanceSettingDO = holidayBalanceSettingService.selectBySettingId(holidaySetting.getId());

        // -- 更新假期额度工龄配置
        boolean changeFlag = this.updateHolidayQuotaAndSeniorityConfiguration(holidaySetting.getId(), oldHolidayBalanceSettingDO.getId(), holidayWorkingAges);
        // -- 1.人员变动 （需要清空多余人员/或者增加新的人员） - 里面已做清空人员处理 - 还没有做清空人员假期余额 在后面的发放中处理
        PersonnelChangesVO personnelChangesVO = this.personnelChanges(holidaySetting.getId(), holidaySettingRanges);
        // -- 2.判断假期余额设置 开关
        // -- 3.假期发放方式调整 历史余额将会被清空 按新的方式重新发送
        // -- 4.发放日期调整  修改发放日期后假期余额将按新规则重新计算
        // -- 5.更改额度配置规则 修改余额发放方式后，假期余额将按新规则重新发放。
        DetermineHolidayBalanceSettingSwitchVO settingSwitch = this.determineHolidayBalanceSettingSwitch(holidayBalanceSetting, oldHolidayBalanceSettingDO, changeFlag);

        LocalDateTime now = LocalDateTime.now();
        // -- 如果我什么都没改 - 岂不是也会更新？ 那么这个月的不久发放不了了么？对吧 我什么都没改的话是不会进行发放的 - 所以这里需要判断他有没有改动什么导致他发放假期 从而更新时间
        if (holidayBalanceSetting.getIssueTime() != null || (settingSwitch.isChangeFlag() && settingSwitch.isSwitchFlag()) ||
                settingSwitch.isAdjustTypeFlag() || settingSwitch.isDateAdjustFlag() || settingSwitch.isQuotaRuleFlag()) {
            LocalDateTime issueTime = this.calculateNextReleaseDate(now, holidayBalanceSetting);
            holidayBalanceSetting.setIssueTime(issueTime);
        }
        holidayBalanceSettingMapper.updateById(holidayBalanceSetting);
        holidayUserRecordService.recalculateAssigned(RecalculateAssignedDTO.builder()
                .holidaySetting(holidaySetting)
                .holidayBalanceSetting(holidayBalanceSetting)
                .holidayWorkingAges(holidayWorkingAges)
                .personnelChangesVO(personnelChangesVO)
                .determineHolidayBalanceSettingSwitchVO(settingSwitch).build());
    }

    /**
     * 更新假期额度工龄配置
     *
     * @param holidaySettingId
     * @param holidayBalanceSettingId
     * @param holidayWorkingAges
     */
    private boolean updateHolidayQuotaAndSeniorityConfiguration(Long holidaySettingId, Long holidayBalanceSettingId, List<HolidayWorkingAgeDO> holidayWorkingAges) {
        List<HolidayWorkingAgeDO> oldHolidayWorkingAgeDOS = holidayWorkingAgeService.selectBySettingId(holidaySettingId);
        boolean flag = false;
        if (CollectionUtil.isNotEmpty(holidayWorkingAges)) {
            for (HolidayWorkingAgeDO workingAgeDO : holidayWorkingAges) {
                workingAgeDO.setHolidaySettingId(holidaySettingId);
                workingAgeDO.setHolidayBalanceSettingId(holidayBalanceSettingId);
            }
            List<HolidayWorkingAgeDO> saveList = holidayWorkingAges.stream().filter(a -> a.getId() == null).collect(Collectors.toList());
            List<HolidayWorkingAgeDO> editList = holidayWorkingAges.stream().filter(a -> a.getId() != null).collect(Collectors.toList());

            if (!saveList.isEmpty()) {
                holidayWorkingAgeMapper.insertBatch(saveList);
                flag = true;
            }
            // - 修改的列表不是 老的子集
            if (!editList.isEmpty() && !CollectionUtil.containsAll(oldHolidayWorkingAgeDOS, editList)) {
                holidayWorkingAgeMapper.updateBatch(editList);
                flag = true;
            }

            List<Long> oldIds = oldHolidayWorkingAgeDOS.stream().map(HolidayWorkingAgeDO::getId).collect(Collectors.toList());
            List<Long> newIds = editList.stream().map(HolidayWorkingAgeDO::getId).collect(Collectors.toList());
            List<Long> delIds = new ArrayList<>(CollectionUtil.subtract(oldIds, newIds));
            if (!delIds.isEmpty()) {
                holidayWorkingAgeMapper.deleteBatchIds(delIds);
                flag = true;
            }
        }
        return flag;
    }

    /**
     * 人员范围计算 (获取到需要删除or新增的人员范围列表)
     *
     * @param holidaySettingId
     * @param holidaySettingRanges
     * @return
     */
    private PersonnelChangesVO personnelChanges(Long holidaySettingId, List<HolidaySettingRangeDO> holidaySettingRanges) {
        PersonnelChangesVO vo = new PersonnelChangesVO();
        List<HolidaySettingRangeDO> oldAllList;
        List<HolidaySettingRangeDO> newAllList;
        List<HolidaySettingRangeDO> delRangeList = new ArrayList<>();
        List<HolidaySettingRangeDO> saveRangeList = new ArrayList<>();
        // -- 查询人员范围列表 判断是否需要更新删除
        LambdaQueryWrapper<HolidaySettingRangeDO> lambdaQueryWrapper = new LambdaQueryWrapper<HolidaySettingRangeDO>()
                .eq(HolidaySettingRangeDO::getHolidaySettingId, holidaySettingId);
        List<HolidaySettingRangeDO> oldHolidaySettingRanges = holidaySettingRangeMapper.selectList(lambdaQueryWrapper);
        newAllList = oldHolidaySettingRanges;
        oldAllList = oldHolidaySettingRanges;
        if (CollectionUtil.isEmpty(holidaySettingRanges)) {
            delRangeList.addAll(oldHolidaySettingRanges);
        } else {
            holidaySettingRanges.forEach(holidaySettingRangeDO -> holidaySettingRangeDO.setHolidaySettingId(holidaySettingId));
            // -- 过滤出所有需要添加的
            List<HolidaySettingRangeDO> saveList = holidaySettingRanges.stream().filter(a -> a.getId() == null).collect(Collectors.toList());
            if (!CollectionUtil.isEmpty(saveList)) {
                saveRangeList.addAll(saveList);
            }
            // -- 过滤出所有需要删除的
            List<Long> ids = holidaySettingRanges.stream().map(HolidaySettingRangeDO::getId).filter(Objects::nonNull).collect(Collectors.toList());
            List<Long> oldIds = oldHolidaySettingRanges.stream().map(HolidaySettingRangeDO::getId).collect(Collectors.toList());
            List<Long> delIds = new ArrayList<>(CollectionUtil.subtract(oldIds, ids));

            if (CollectionUtil.isNotEmpty(delIds)) {
                List<HolidaySettingRangeDO> delList = oldHolidaySettingRanges.stream().filter(a -> delIds.contains(a.getId())).collect(Collectors.toList());
                delRangeList.addAll(delList);
            }
        }
        if (CollectionUtil.isNotEmpty(delRangeList)) {
            newAllList.removeAll(delRangeList);
            holidaySettingRangeMapper.deleteBatchIds(delRangeList);
        }
        if (CollectionUtil.isNotEmpty(saveRangeList)) {
            newAllList.addAll(saveRangeList);
            holidaySettingRangeMapper.insertBatch(saveRangeList);
        }
        return vo.setOldAllList(oldAllList).setSaveList(saveRangeList).setDelList(delRangeList).setNewAllList(newAllList);
    }

    /**
     * 判断假期余额设置
     *
     * @param holidayBalanceSetting      新的假期余额设置
     * @param oldHolidayBalanceSettingDO 老的假期余额设置
     * @param changeFlag
     */
    private DetermineHolidayBalanceSettingSwitchVO determineHolidayBalanceSettingSwitch(HolidayBalanceSettingDO holidayBalanceSetting, HolidayBalanceSettingDO oldHolidayBalanceSettingDO, boolean changeFlag) {
        boolean quotaRuleFlag = !holidayBalanceSetting.getQuotaRule().equals(oldHolidayBalanceSettingDO.getQuotaRule());
        // - 如果两个额度相等并且是固定额度 并且两个值不想等  || 或者阶梯有更改
        boolean quotaFlag = oldHolidayBalanceSettingDO.getQuotaRule() == 1 ? !holidayBalanceSetting.getQuota().equals(oldHolidayBalanceSettingDO.getQuota()) : changeFlag;
        return DetermineHolidayBalanceSettingSwitchVO.builder()
                .changeFlag(!Objects.equals(holidayBalanceSetting.getStatus(), oldHolidayBalanceSettingDO.getStatus()))
                .switchFlag(Constants.TRUE.equals(holidayBalanceSetting.getStatus()))
                .adjustTypeFlag(!holidayBalanceSetting.getType().equals(oldHolidayBalanceSettingDO.getType()))
                .dateAdjustFlag(!holidayBalanceSetting.getIssueTimeType().equals(oldHolidayBalanceSettingDO.getIssueTimeType()))
                .quotaRuleFlag(quotaRuleFlag)
                .quotaFlag(quotaRuleFlag || quotaFlag)
                .build();
    }

}
