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

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAOvertimeItemDO;
import cn.iocoder.yudao.module.system.api.attendance.vo.AttendancePunchRecordVO;
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 javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 加班 工作日
 *
 * @author 艾楷
 */
@Service("weekDay")
@Validated
public class WorkOvertimeWeekDayServiceImpl implements WorkOvertimeWeekDayService, WorkOvertimeService {

    @Resource
    private WorkOvertimePublicService workOvertimePublicService;

    @Override
    public void getOvertimeHours(BpmOAOvertimeItemDO item, List<AttendancePunchRecordVO> recordList, WorkOvertimeRuleApiVO rule, WorkOvertimeRuleItemApiVO ruleItem) {
        // --- 计算方式 1按审批时长计算 2在审批的时段内，按打卡时长计算 3无需审批，按打卡时长计算  (这里是审批后的节点 只计算 1和2两种情况)
        // --------------------- 按审批时长计算 ---------------------
        if (ruleItem.getCalculationMode() == 1) {
            item.setActualTimeLength(item.getTimeLength());
            return;
        }
        // --------------------- 在审批的时段内，按打卡时长计算 ---------------------
        BigDecimal overtimeHours = BigDecimal.ZERO;
        long totalMillis = 0L;
        //首先判断下
        if (Arrays.asList(1, 2).contains(ruleItem.getAllowOvertimeTimeType())) {
            // 合并 AttendancePunchRecordVO列表中 UpWorkOvertimeTime 的和
            Long upWorkOvertimeTime = recordList.stream().filter(a ->
                            //获取正常打卡的上班卡
                            a.getStatus().equals(0) && a.getWorkType().equals(0)
                                    // 计算班前多少分钟 小于n分钟 则不考虑
                                    && a.getUpWorkOvertimeTime() > 0 && TimeUnit.MILLISECONDS.toMinutes(a.getUpWorkOvertimeTime()) > ruleItem.getBeforeWorkOvertime())
                    .map(AttendancePunchRecordVO::getUpWorkOvertimeTime)
                    // TODO: 2024/11/9 这行计算有问题
                    .reduce(0L, Long::sum);
            // -- 转换为分钟
            long millis = TimeUnit.MILLISECONDS.toMinutes(upWorkOvertimeTime);
            totalMillis += millis;
        }

        if (Arrays.asList(1, 3).contains(ruleItem.getAllowOvertimeTimeType())) {
            // 先将所有下班加班时长减去 下班加班起算时间
            recordList.forEach(a -> {
                long millis = TimeUnit.MINUTES.toMillis(ruleItem.getOvertimeStartingTime());
                if (millis > 0) {
                    a.setDownWorkOvertimeTime(Math.max(a.getDownWorkOvertimeTime() - millis, 0));
                }
            });
            // 计算加班时长
            Long downWorkOvertimeTime = recordList.stream().filter(a ->
                            //获取正常打卡的下班卡
                            a.getStatus().equals(0) && a.getWorkType().equals(1)
                                    //计算班后多少分钟 小于n分钟 则不考虑
                                    && a.getDownWorkOvertimeTime() > 0 && TimeUnit.MILLISECONDS.toMinutes(a.getDownWorkOvertimeTime()) >= ruleItem.getAfterWorkOvertime()
                    ).map(AttendancePunchRecordVO::getDownWorkOvertimeTime)
                    .reduce(0L, Long::sum);
            // 下班n分钟后开始算加班 -
            long millis = TimeUnit.MILLISECONDS.toMinutes(downWorkOvertimeTime);
            totalMillis += millis;
        }
        // -- 计算取整 - 插入加班时间到item中
        workOvertimePublicService.calculateActualTimeLength(totalMillis, rule, item, ruleItem);
    }

    public static void main(String[] args) {
        // 合并 AttendancePunchRecordVO列表中 UpWorkOvertimeTime 的和
        List<AttendancePunchRecordVO> recordList = new ArrayList<>();
        List<Long> collect = recordList.stream().filter(a ->
                        //获取正常打卡的上班卡
                        TimeUnit.MILLISECONDS.toMinutes(23114096L) > 30)
                .map(AttendancePunchRecordVO::getUpWorkOvertimeTime).collect(Collectors.toList());
        System.out.println(collect );
        System.out.println(collect );

        LocalDateTime localDateTime = LocalDateTime.of(2024, 6, 25, 17, 30, 0);
        LocalDateTime plus = localDateTime.plus(1931472, ChronoUnit.MILLIS);
        long between = LocalDateTimeUtil.between(localDateTime, plus, ChronoUnit.MINUTES);
        System.out.println(plus);
        System.out.println(between);
        // 将1931472毫秒转换为分钟
        long millis = TimeUnit.MINUTES.toMillis(1);
        System.out.println(millis);
//        List<AttendancePunchRecordVO> recordList = Arrays.asList(
//                new AttendancePunchRecordVO().setStatus(0).setWorkType(1).setUpWorkOvertimeTime(20L),
//                new AttendancePunchRecordVO().setStatus(0).setWorkType(1).setUpWorkOvertimeTime(10L)
//        );
//        Long upWorkOvertimeTime = recordList.stream().filter(a -> a.getStatus().equals(0) && a.getWorkType().equals(1)).map(AttendancePunchRecordVO::getUpWorkOvertimeTime)
//                .reduce(0L, Long::sum);
//        System.out.println(upWorkOvertimeTime);

    }
}
