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

import com.google.common.collect.Lists;

import java.lang.reflect.Field;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.chrono.ChronoLocalDate;
import java.time.chrono.ChronoLocalDateTime;
import java.util.Set;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.logging.Log;
import kd.bos.logging.LogFactory;
import kd.sdk.wtc.wtes.business.tie.init.bill.TvlBillTimeBucketSplitEvent;
import kd.sdk.wtc.wtes.business.tie.init.bill.TvlBillTimeBucketSplitExtPlugin;
import kd.sdk.wtc.wtes.business.tie.model.roster.RosterExt;
import kd.sdk.wtc.wtes.business.tie.model.roster.ShiftSpecExt;
import kd.sdk.wtc.wtes.business.tie.model.roster.ShiftTableSingleExt;
import kd.sdk.wtc.wtes.business.tie.model.timebucket.AttBillTimeBucketExt;
import kd.wtc.wtes.business.ext.model.roster.RosterExtImpl;
import org.apache.curator.shaded.com.google.common.collect.Sets;
/**
 * Description      :出差核算时长计算扩展，处理跨天逻辑，去除休息时长
 * 反编译标品 kd.sdk.wtc.wtes.business.tie.init.bill.TvlBillTimeBucketSplitExtPluginDemo
 * @author Tyx
 * @date  2025/5/16
 * 标识 nckd_casrecrapply
 */

public class TvlBillTimeBucketSplitExtPluginEx implements TvlBillTimeBucketSplitExtPlugin {

    private static Log log = LogFactory.getLog(TvlBillTimeBucketSplitExtPluginEx.class);

    @Override
    public void splitVaBillTimeBucket(TvlBillTimeBucketSplitEvent tvlBillTimeBucketSplitEvent) {
        log.info("出差核算时长二开开始");
        Set<AttBillTimeBucketExt> timeBucketExtSetRes = Sets.newHashSet();
        for (AttBillTimeBucketExt billTimeBucketExt : tvlBillTimeBucketSplitEvent.getAttBillTimeBucketExtList()) {
            DynamicObject entryRowDy = billTimeBucketExt.getEntryRowDy();
            ShiftTableSingleExt shiftTableSingleExt = tvlBillTimeBucketSplitEvent.getShiftTableExt().shiftTableSingle(billTimeBucketExt.getAttPersonId());
            if (entryRowDy != null && "3".equals(entryRowDy.getString("startmethod"))) {
                LocalDateTime startDate = billTimeBucketExt.getStartTime();
                LocalDateTime endDate = billTimeBucketExt.getEndTime();
                // 2025-05-20 Tyx 如果endDate > shiftendDate 则取shiftendDate
                LocalDate shiftstartDate = tvlBillTimeBucketSplitEvent.getStartDate();
                LocalDate shiftendDate = tvlBillTimeBucketSplitEvent.getEndDate();
                Set<AttBillTimeBucketExt> timeBucketExtSet = Sets.newHashSet();
                LocalDate date = LocalDate.of(2025,6, 1);
                while (shiftstartDate.compareTo((ChronoLocalDate)shiftendDate) <= 0) {
                    //正式环境 加个判断 需要大于6-1
//                    if(shiftstartDate.compareTo(date) < 0) {
//                        log.info("shiftstartDate : " + shiftstartDate);
//                        shiftstartDate = shiftstartDate.plusDays(1L);
//                        continue;
//                    }
                    log.info("出差核算：" + shiftstartDate);
                    LocalDateTime shiftStart = this.getshiftStartDateTime(shiftstartDate, shiftTableSingleExt);
                    LocalDateTime shiftEnd = this.getshiftEndDateTime(shiftstartDate, shiftTableSingleExt);
                    LocalDateTime shiftStartNext = this.getshiftStartDateTime(shiftstartDate.plusDays(1L), shiftTableSingleExt);
                    if(shiftStart == null || shiftEnd == null || shiftStartNext == null) {
                        shiftstartDate = shiftstartDate.plusDays(1L);
                        continue;
                    }
                    LocalDateTime start = (startDate.compareTo((ChronoLocalDateTime<?>)shiftStart) > 0) ? startDate : shiftStart;
                    LocalDateTime end = (endDate.compareTo((ChronoLocalDateTime<?>)shiftStartNext) < 0) ? endDate : shiftEnd;
                    if (start.compareTo((ChronoLocalDateTime<?>)end) < 0) {
                        timeBucketExtSet.add(billTimeBucketExt.newInstanceResetTime(billTimeBucketExt, shiftstartDate, start, end));
                    }
                    shiftstartDate = shiftstartDate.plusDays(1L);
                }
                if (timeBucketExtSet.isEmpty()) {
                    timeBucketExtSet.add(billTimeBucketExt);
                }
                timeBucketExtSetRes.addAll(timeBucketExtSet);
            }
        }
        tvlBillTimeBucketSplitEvent.setAttBillTimeBucketExtList(Lists.newArrayList((Iterable)timeBucketExtSetRes));
    }

    private LocalDateTime getshiftStartDateTime(final LocalDate localDate, final ShiftTableSingleExt shiftTableSingleExt) {
        final RosterExt rosterExt = shiftTableSingleExt.getRoster(localDate);
        if(isRosterNull(rosterExt)){
            log.info("getshiftStartDateTime Null：" + localDate);
            return null;
        }
        final ShiftSpecExt shiftSpecExt = rosterExt.getShiftSpec();
        if (shiftSpecExt.isOffNonPlan()) {
            return this.getshiftStartDateTimeNoPlan(localDate, shiftTableSingleExt);
        }
        return this.getshiftStartDateTimeHasPlan(localDate, shiftTableSingleExt);
    }

    private LocalDateTime getshiftStartDateTimeNoPlan(final LocalDate localDate, final ShiftTableSingleExt shiftTableSingleExt) {
        final RosterExt rosterExt = shiftTableSingleExt.getRoster(localDate);
        final ShiftSpecExt shiftSpecExt = rosterExt.getShiftSpec();
        LocalDateTime shiftStart = localDate.atStartOfDay();
        if (shiftSpecExt.isOffNonPlan()) {
            final RosterExt preRosterExt = shiftTableSingleExt.getRoster(localDate.plusDays(-1L));
            final ShiftSpecExt preShiftSpecExt = preRosterExt.getShiftSpec();
            if (!preShiftSpecExt.isOffNonPlan()) {
                final LocalDateTime preShiftEndDateTime = this.getshiftEndDateTime(localDate.plusDays(-1L), shiftTableSingleExt);
                shiftStart = ((shiftStart.compareTo((ChronoLocalDateTime<?>)preShiftEndDateTime) > 0) ? shiftStart : preShiftEndDateTime);
            }
        }
        return shiftStart;
    }

    public static boolean isRosterNull(RosterExt rosterExt) {
        try {
            // 获取私有字段
            Field rosterField = rosterExt.getClass().getDeclaredField("roster");
            // 设置可访问性（突破private限制）
            rosterField.setAccessible(true);
            // 获取字段值并判断
            return rosterField.get(rosterExt) == null;
        } catch (NoSuchFieldException | IllegalAccessException e) {
            e.printStackTrace();
            return true;
        }
    }

    private LocalDateTime getshiftStartDateTimeHasPlan(final LocalDate localDate, final ShiftTableSingleExt shiftTableSingleExt) {
        final RosterExt rosterExt = shiftTableSingleExt.getRoster(localDate);
        final ShiftSpecExt shiftSpecExt = rosterExt.getShiftSpec();
        LocalDateTime shiftStart = localDate.atStartOfDay();
        if (shiftSpecExt.isOffNonPlan()) {
            return shiftStart;
        }
        if (RefDateType.TODAY.code.equals(shiftSpecExt.getFirstRefDateType())) {
            shiftStart = LocalDateTime.of(localDate, shiftSpecExt.getEarliestShiftTime());
        }
        else if (RefDateType.NEXTDAY.code.equals(shiftSpecExt.getFirstRefDateType())) {
            shiftStart = LocalDateTime.of(localDate.plusDays(1L), shiftSpecExt.getEarliestShiftTime());
        }
        else if (RefDateType.LASTDAY.code.equals(shiftSpecExt.getFirstRefDateType())) {
            shiftStart = LocalDateTime.of(localDate.plusDays(-1L), shiftSpecExt.getEarliestShiftTime());
        }
        return shiftStart;
    }

    private LocalDateTime getshiftEndDateTime(final LocalDate localDate, final ShiftTableSingleExt shiftTableSingleExt) {
        final RosterExt rosterExt = shiftTableSingleExt.getRoster(localDate);
        if(isRosterNull(rosterExt)){
            log.info("getshiftEndDateTime Null：" + localDate);
            return null;
        }
        final ShiftSpecExt shiftSpecExt = rosterExt.getShiftSpec();
        LocalDateTime shiftEnd = localDate.plusDays(1L).atStartOfDay();
        if (shiftSpecExt.isOffNonPlan()) {
            return shiftEnd;
        }
        if (RefDateType.TODAY.code.equals(shiftSpecExt.getLastRefDateType())) {
            shiftEnd = LocalDateTime.of(localDate, shiftSpecExt.getLastShiftTime());
        }
        else if (RefDateType.NEXTDAY.code.equals(shiftSpecExt.getLastRefDateType())) {
            shiftEnd = LocalDateTime.of(localDate.plusDays(1L), shiftSpecExt.getLastShiftTime());
        }
        else if (RefDateType.LASTDAY.code.equals(shiftSpecExt.getLastRefDateType())) {
            shiftEnd = LocalDateTime.of(localDate.plusDays(-1L), shiftSpecExt.getLastShiftTime());
        }
        return shiftEnd;
    }

    enum RefDateType
    {
        TODAY("D"),
        NEXTDAY("C"),
        LASTDAY("Q");

        public final String code;

        private RefDateType(final String code) {
            this.code = code;
        }
    }
}
