package jnpf.attendance.service.handle.rule;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSON;
import jnpf.attendance.service.RuleProcessor;
import jnpf.constants.AttendanceConstant;
import jnpf.entity.attendance.FtbAttendanceDailyRule;
import jnpf.enums.attendance.AttendanceTypeEnum;
import jnpf.model.attendance.vo.DailyRuleResultVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 处理历史排休
 */
@Component
@Slf4j
public class RestRuleProcessor extends RuleProcessor {
    @Override
    public void ruleArrangementHandle(List<FtbAttendanceDailyRule> hisDailyRules, List<FtbAttendanceDailyRule> currDailyRule, List<DailyRuleResultVo> resultList) {

        Map<Integer, List<FtbAttendanceDailyRule>> collect = hisDailyRules.stream().collect(Collectors.groupingBy(FtbAttendanceDailyRule::getAttendanceType));
        List<FtbAttendanceDailyRule> ftbAttendanceDailyRules = CollUtil.newArrayList();
        if (collect.containsKey(AttendanceTypeEnum.DEFAULT.getCode())) {
            hisDailyRules.removeAll(collect.get(AttendanceTypeEnum.DEFAULT.getCode()));
        }
        if (collect.containsKey(AttendanceTypeEnum.REST.getCode())) {
            ftbAttendanceDailyRules.addAll(collect.getOrDefault(AttendanceTypeEnum.REST.getCode(), List.of()).stream().filter(rule -> !rule.getIsInsert()).collect(Collectors.toList()));
        }
        if (collect.containsKey(AttendanceTypeEnum.HOLIDAYS.getCode())) {
            ftbAttendanceDailyRules.addAll(collect.get(AttendanceTypeEnum.HOLIDAYS.getCode()));
        }
        if (collect.containsKey(AttendanceTypeEnum.DEDUCTION_HOLIDAYS.getCode())) {
            ftbAttendanceDailyRules.addAll(collect.get(AttendanceTypeEnum.DEDUCTION_HOLIDAYS.getCode()));
        }
        if (collect.containsKey(AttendanceTypeEnum.EXCHANGE_HOLIDAYS.getCode())) {
            ftbAttendanceDailyRules.addAll(collect.get(AttendanceTypeEnum.EXCHANGE_HOLIDAYS.getCode()));
        }
        if (CollUtil.isNotEmpty(ftbAttendanceDailyRules)) {
            Iterator<FtbAttendanceDailyRule> iterator = currDailyRule.iterator();
            while (iterator.hasNext()) {
                FtbAttendanceDailyRule rule = iterator.next();
                //新增清除
                if (clearHandle(hisDailyRules, ftbAttendanceDailyRules, rule, resultList)) {
                    continue;
                }
                if (stepOutHandle(hisDailyRules, ftbAttendanceDailyRules, rule, resultList)) {
                    continue;
                }
                if (Objects.equals(AttendanceTypeEnum.LEAVE.getCode(), rule.getAttendanceType())) {
                    if (!hisDailyRules.contains(rule)) {
                        rule.setApplyViewEnable(0);
                        rule.insertTrue();
                        hisDailyRules.add(rule);
                    }
                    continue;
                }
                if (Objects.equals(AttendanceTypeEnum.WORKOVERTIME.getCode(), rule.getAttendanceType())) {
                    if (!hisDailyRules.contains(rule)) {
                        rule.setApplyViewEnable(1);
                        rule.insertTrue();
                        hisDailyRules.add(rule);
                        resultList.add(DailyRuleResultVo.successBuild(rule));
                    }
                    continue;
                }
                if (Objects.equals(AttendanceTypeEnum.REST.getCode(), rule.getAttendanceType()) || Objects.equals(AttendanceTypeEnum.ORDINARY.getCode(), rule.getAttendanceType())) {
                    log.error("新增{}覆盖原来休{}",AttendanceTypeEnum.getEnum(rule.getAttendanceType()).getMsg(), JSON.toJSONString(rule));
                    ftbAttendanceDailyRules.forEach(oldRule -> {
                        hisDailyRules.remove(oldRule);
                        resultList.add(DailyRuleResultVo.successRestBuild(oldRule, rule, rule.getPeriodWorkDay()));
                    });
                    if (!hisDailyRules.contains(rule)) {
                        rule.setApplyViewEnable(1);
                        hisDailyRules.add(rule);
                    }
                    continue;
                }
                ftbAttendanceDailyRules.forEach(oldRule -> {
                    resultList.add(DailyRuleResultVo.successRestBuild(oldRule, rule, oldRule.getPeriodWorkDay()));
                });

                rule.insertTrue();
                if (!hisDailyRules.contains(rule)) {
                    if (!Objects.equals(AttendanceTypeEnum.WORKOVERTIME.getCode(), rule.getAttendanceType())) {
                        rule.setApplyViewEnable(1);
                    }
                    hisDailyRules.add(rule);
                }

            }
        }
        if (Objects.nonNull(nextRuleProcessor)) {
            nextRuleProcessor.ruleArrangementHandle(hisDailyRules, currDailyRule, resultList);
        }
    }

    /**
     * 新增外出、出差申请
     *
     * @param hisDailyRules           历史规则
     * @param ftbAttendanceDailyRules 新增规则集合
     * @param rule                    当前规则
     */
    private Boolean stepOutHandle(List<FtbAttendanceDailyRule> hisDailyRules, List<FtbAttendanceDailyRule> ftbAttendanceDailyRules, FtbAttendanceDailyRule rule, List<DailyRuleResultVo> resultList) {
        //新增请假
        if (!Objects.equals(AttendanceTypeEnum.BUSINESS_TRIP.getCode(), rule.getAttendanceType()) && !Objects.equals(AttendanceTypeEnum.STEP_OUT.getCode(), rule.getAttendanceType())) {
            return Boolean.FALSE;
        }
        ftbAttendanceDailyRules.forEach(oldRule -> {
            //新加入数据不做处理
            if (oldRule.getIsInsert()) {
                return;
            }
            rule.setShiftId(oldRule.getShiftId());
            rule.setPeriodId(oldRule.getPeriodId());
            rule.setApplyViewEnable(0);
            rule.insertTrue();
            oldRule.setInPoint(rule.getInPoint());
            oldRule.setOutPoint(rule.getOutPoint());
            oldRule.setInStepOutType(1);
            oldRule.setOutStepOutType(1);
            oldRule.setInStepOutApplyId(rule.getApplyId());
            oldRule.setOutStepOutApplyId(rule.getApplyId());
            oldRule.setApplyViewEnable(rule.getAttendanceType());
            if (!hisDailyRules.contains(rule)) {
                hisDailyRules.add(rule);
            }
            log.error("新增外出、出差申请标记原排休时段{}", JSON.toJSONString(rule));
            resultList.add(DailyRuleResultVo.successBuild(oldRule, rule));
        });
        return Boolean.TRUE;
    }

    /**
     * 新增清除
     *
     * @param hisDailyRules           历史规则
     * @param ftbAttendanceDailyRules 新增规则集合
     * @param rule                    当前规则
     */
    private Boolean clearHandle(List<FtbAttendanceDailyRule> hisDailyRules, List<FtbAttendanceDailyRule> ftbAttendanceDailyRules, FtbAttendanceDailyRule rule, List<DailyRuleResultVo> resultList) {
        //新增清除
        if (!Objects.equals(AttendanceTypeEnum.CLEAR.getCode(), rule.getAttendanceType())) {
            return Boolean.FALSE;
        }
        ftbAttendanceDailyRules.forEach(oldRule -> {
            resultList.add(DailyRuleResultVo.successBuild(oldRule));
            hisDailyRules.remove(oldRule);
        });
        return Boolean.TRUE;
    }
}
