package cn.iocoder.yudao.module.bpm.service.workovertime;

import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAOvertimeItemDO;
import cn.iocoder.yudao.module.system.api.workovertime.vo.WorkOvertimeDeductRuleApiVO;
import cn.iocoder.yudao.module.system.api.workovertime.vo.WorkOvertimeRuleApiVO;
import cn.iocoder.yudao.module.system.api.workovertime.vo.WorkOvertimeRuleItemApiVO;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.Comparator;
import java.util.List;

/**
 * 加班 节假日
 *
 * @author 艾楷
 */
@Service
@Validated
public class WorkOvertimePublicServiceImpl implements WorkOvertimePublicService {


    @Override
    public long calculateDeductedTime(long millis, List<WorkOvertimeDeductRuleApiVO> deductRules) {
        deductRules.sort(Comparator.comparing(WorkOvertimeDeductRuleApiVO::getThreshold).reversed());
        for (WorkOvertimeDeductRuleApiVO rule : deductRules) {
            long deductNum = rule.getDeductNum() * 60;
            long threshold = rule.getThreshold() * 60;
            if (millis >= threshold) {
                millis = millis - deductNum;
                break;
            }
        }
        // 确保扣除后的时长不为负数
        return millis < 0 ? 0L : millis;
    }

    @Override
    public void calculateActualTimeLength(long millis, WorkOvertimeRuleApiVO rule, BpmOAOvertimeItemDO item, WorkOvertimeRuleItemApiVO ruleItem) {
        BigDecimal overtimeHours = BigDecimal.ZERO;
        // -- 累计加班少于多少分钟，不计入加班
        if (millis < ruleItem.getOvertimeTotalHours()) {
            item.setActualTimeLength(overtimeHours);
            return;
        }
        // -- 先扣除休息时间 - 这里计算的是分钟
        if (ruleItem.getIsDeductBreakTime() == 1 && CollUtil.isNotEmpty(ruleItem.getDeductRules())) {
            List<WorkOvertimeDeductRuleApiVO> deductRules = ruleItem.getDeductRules();
            millis = this.calculateDeductedTime(millis, deductRules);
        }

        if (rule.getMoreRule().getUnit() == 1) {
            // ------ 转为小时后取整
            overtimeHours = BigDecimal.valueOf(millis).divide(BigDecimal.valueOf(60.0), 2, RoundingMode.HALF_UP);
        } else {
            overtimeHours = BigDecimal.valueOf(millis).divide(BigDecimal.valueOf(60.0 * 24), 2, RoundingMode.HALF_UP);
        }
        if (rule.getMoreRule().getRoundingType() == 1) {
            //向下取整
            overtimeHours = calculateAdjustedOvertime(overtimeHours, rule.getMoreRule().getRoundingIncrementalValue());
        }
        item.setActualTimeLength(overtimeHours);
        item.setUnit(rule.getMoreRule().getUnit());
        item.setActualTimeLengthMinutes(millis);
    }

    public static void main(String[] args) {
        System.out.println(calculateAdjustedOvertime(BigDecimal.valueOf(3.0), BigDecimal.valueOf(1.5)));
    }

    /**
     * 向下取整
     *
     * @param time
     * @param n
     * @return
     */
    public static BigDecimal calculateAdjustedOvertime(BigDecimal time, BigDecimal n) {
        if (n.compareTo(BigDecimal.ZERO) <= 0) {
            return BigDecimal.ZERO;
        }
        // 计算商
        BigDecimal quotient = time.divide(n, MathContext.DECIMAL128).setScale(0, RoundingMode.DOWN);
        // 商乘以 n，得到最终的加班时长
        return quotient.multiply(n);
    }

}
