package nckd.jimin.jyyy.hr.wtc.wtam.explugin;

import kd.bos.logging.Log;
import kd.bos.logging.LogFactory;
import kd.sdk.wtc.wtam.business.applytime.TpApplyTimeCalculateEvent;
import kd.sdk.wtc.wtam.business.applytime.TpApplyTimeCalculateExtPlugin;
import kd.sdk.wtc.wtbs.common.dto.shift.ShiftDetailDto;
import kd.sdk.wtc.wtbs.common.dto.shift.ShiftDto;
import kd.wtc.wtbs.business.util.ShiftParseUtil;
import kd.wtc.wtbs.common.model.evaluation.ShiftDetail;
import kd.wtc.wtbs.common.model.shift.RefDateType;
import kd.wtc.wtbs.common.util.WTCDateUtils;
import kd.wtc.wtbs.common.util.third.util.DateUtils;
import kd.wtc.wtbs.common.util.third.util.StringUtils;
import kd.wtc.wtes.business.model.shift.OutWorkType;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Description      :出差申请时长计算扩展，处理跨天逻辑，去除休息时长
 * @author Tyx
 * @date  2025/5/16
 * 标识 nckd_casrecrapply
 */


public class TpApplyTimeCalculateExtPluginEx implements TpApplyTimeCalculateExtPlugin {
    private static Log log = LogFactory.getLog(TpApplyTimeCalculateExtPluginEx.class);
    @Override
    public void onCalculateApplyTime(TpApplyTimeCalculateEvent tpApplyTimeCalculateEvent) {
        log.info("开始执行出差单申请时长计算扩展：");
        //时长类型，非时分的情况下直接返回
        String unit = tpApplyTimeCalculateEvent.getEntryDy().getString("unit");
        if(!"B".equals(unit))
            return;
        Date startDate = tpApplyTimeCalculateEvent.getEntryDy().getDate("startdate");       //分录出差开始时间
        LocalDate startLocalDate = startDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();   //分录出差开始时间
        Date endDate = tpApplyTimeCalculateEvent.getEntryDy().getDate("enddate");         //分录出差结束时间
        LocalDate endLocalDate = endDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();       //分录出差结束时间
        //String startDateStr = sdf.format(startDate);
        //String endDateStr = sdf.format(endDate);
        //排班信息 key：日期，value：shiftDto
        Map shiftMap = tpApplyTimeCalculateEvent.getShiftMap();

        //默认班次时长
        ShiftDto defaultShift = (ShiftDto) shiftMap.get(startLocalDate);
        BigDecimal defaultDayHours = defaultShift.getShiftMiddleRuleDto().getAlldayhour();
        BigDecimal DECIMAL_ONE_HOUR_SECONDS =  new BigDecimal(3600L);
        BigDecimal defaultDayHoursLong = defaultDayHours.multiply(DECIMAL_ONE_HOUR_SECONDS);
        log.info("默认班次时长：{}，默认班次时长（秒）：{}", defaultDayHours, defaultDayHoursLong);
        //相差天数
        long days = ChronoUnit.DAYS.between(startLocalDate, endLocalDate);

        //计算时长
        BigDecimal valHours = BigDecimal.ZERO;
        BigDecimal sumHours = BigDecimal.ZERO;
        BigDecimal sumDays = BigDecimal.ZERO;
        for (int i = 0 ; i <= days; i++) {
            // i == 0时，为出差开始这天，单独处理时长; i == days为出差结束这天，单独处理时长
            if(i == 0 || i == days) {
                Instant instant = null;
                if(i == 0) {
                    instant = startLocalDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant();
                }
                else if (i == days) {
                    instant = endLocalDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant();
                }
                ShiftDto shiftDto = (ShiftDto) shiftMap.get(startLocalDate);
                BigDecimal calHours = dealDayApplyTime(startDate, endDate, shiftDto, Date.from(instant));
                valHours = valHours.add(calHours);
                log.info("{} : 计算时长为 : {}", Date.from(instant), valHours);
            }
            // i <> 0 && i <> days时，为中间段日期，默认按班次时长计算
            if(i != 0 && i != days) {
                valHours = valHours.add(defaultDayHoursLong);
            }
        }
        // 转换成小时
        sumHours = valHours.divide(DECIMAL_ONE_HOUR_SECONDS, 6, RoundingMode.HALF_UP);
        // 转换成天数
        sumDays = sumHours.divide(defaultDayHours, 6, RoundingMode.HALF_UP);
        // 回写结果
        tpApplyTimeCalculateEvent.getResult().setValHour(sumHours);
        tpApplyTimeCalculateEvent.getResult().setValDay(sumDays);
    }

    /**
     * 根据班次计算每天的出差时长
     * @param startDate  出差开始时间
     * @param endDate    出差结束时间
     * @param shiftDto   班次信息
     * @param rosterDate 班次时间
     */
    public BigDecimal dealDayApplyTime (Date startDate, Date endDate, ShiftDto shiftDto, Date rosterDate) {
        List<ShiftDetailDto> shiftList = shiftDto.getShiftDetailDtoList();
        BigDecimal sumHours = BigDecimal.ZERO;
        for(ShiftDetailDto detailDto : shiftList) {
            if(detailDto.getOutWorkType().equals(OutWorkType.BREAK.code))
                continue;
            Date prevEndDateTime = getRosterStartDate(detailDto, rosterDate);
            Date detailEndDate = getRosterDetailEndDate(detailDto, rosterDate);
            long shiftDetailInsectionTimes = WTCDateUtils.getDateInsectionTimes(startDate, endDate, prevEndDateTime, detailEndDate);
            sumHours = sumHours.add(BigDecimal.valueOf(shiftDetailInsectionTimes));
        }
        return sumHours;
    }

    public static Date getRosterStartDate(ShiftDetailDto detail, Date rosterDate) {
        Date date = rosterDate;
        String refStartDay = detail.getRefStartDay();
        if (StringUtils.equals(RefDateType.NEXTDAY.code, refStartDay)) {
            date = DateUtils.addDays(rosterDate, 1);
        }

        int shiftStartDate = detail.getShiftStartDate();
        date = WTCDateUtils.getDate(date, shiftStartDate);
        return date;
    }

    public static Date getRosterDetailEndDate(ShiftDetailDto shiftDetail, Date rosterDate) {
        Date rosterShiftEndDate = WTCDateUtils.getDate(rosterDate, shiftDetail.getShiftEndDate());
        if (StringUtils.equals(shiftDetail.getRefEndDay(), RefDateType.NEXTDAY.code)) {
            rosterShiftEndDate = DateUtils.addDays(rosterShiftEndDate, 1);
        }

        return rosterShiftEndDate;
    }


}
