package com.engine.kq.biz.chain.duration;

import com.alibaba.fastjson.JSON;
import com.engine.kq.biz.KQExitRulesBiz;
import com.engine.kq.biz.KQLeaveRulesComInfo;
import com.engine.kq.biz.KQSettingsBiz;
import com.engine.kq.biz.KQShiftRuleInfoBiz;
import com.engine.kq.biz.KQTimesArrayComInfo;
import com.engine.kq.biz.KQTravelRulesBiz;
import com.engine.kq.biz.chain.cominfo.HalfShiftComIndex;
import com.engine.kq.biz.chain.cominfo.ShiftInfoCominfoBean;
import com.engine.kq.biz.chain.shiftinfo.ShiftInfoBean;
import com.engine.kq.enums.DurationTypeEnum;
import com.engine.kq.log.KQLog;
import com.engine.kq.util.KQDurationCalculatorUtil;
import com.engine.kq.wfset.bean.SplitBean;
import com.engine.kq.wfset.util.SplitActionUtil;
import com.engine.kq.wfset.util.SplitSelectSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;
import weaver.general.Util;

/**
 * 工作时长 按半天计算
 */
public class WorkHalfUnitSplitChain extends WorkDurationChain {

  public static KQLog kqLog = new KQLog();

  /**
   * 半天规则下 上午-上午
   */
  public static final int fore_fore_index = 0;

  /**
   * 半天规则下 上午-下午
   */
  public static final int fore_after_index = 1;

  /**
   * 半天规则下 下午-上午
   */
  public static final int after_fore_index = 2;

  /**
   * 半天规则下 下午-下午
   */
  public static final int after_after_index = 3;

  /**
   * 半天规则下 非工作日中间点 12:00
   */
  public static final String non_work_half_time = "12:00";


  public WorkHalfUnitSplitChain(List<SplitBean> splitBeans) {
    super(splitBeans);
  }

  @Override
  public void handleDuration(SplitBean splitBean) throws Exception{
    String durationrule = splitBean.getDurationrule();
    if("2".equalsIgnoreCase(durationrule)){
      String timeselection = "1";
      if(splitBean.getDurationTypeEnum() == DurationTypeEnum.EVECTION){
        timeselection = KQTravelRulesBiz.getTimeselection();
      }
      if(splitBean.getDurationTypeEnum() == DurationTypeEnum.OUT){
        timeselection = KQExitRulesBiz.getTimeselection();
      }
      if(splitBean.getDurationTypeEnum() == DurationTypeEnum.LEAVE || splitBean.getDurationTypeEnum() == DurationTypeEnum.LEAVEBACK){
        KQLeaveRulesComInfo kqLeaveRulesComInfo = new KQLeaveRulesComInfo();
        timeselection = kqLeaveRulesComInfo.getTimeSelection(splitBean.getNewLeaveType());
      }
      splitBean.setTimeselection(timeselection);
      if("2".equalsIgnoreCase(timeselection)){
        //按照具体时间来算半天的话，还是要按照班次来拆分每一天
        SplitActionUtil splitActionUtil = new SplitActionUtil();
        splitActionUtil.doSerialSplitList(splitBean, splitBeans);
      }else{
        getSplitDurationBean(splitBean);
      }
    }else{
      this.success.handleDuration(splitBean);
    }
  }

  /**
   * 工作日根据具体时间来计算半天
   * @param initArrays
   * @param shiftInfoBean
   * @param kqTimesArrayComInfo
   * @param splitBean
   * @param flowbegintimeIndex
   * @param flowendtimeIndex
   */
  public static boolean getSplitDurationBean4Time(int[] initArrays,
      ShiftInfoBean shiftInfoBean, KQTimesArrayComInfo kqTimesArrayComInfo,
      SplitBean splitBean, int flowbegintimeIndex, int flowendtimeIndex){

    boolean isSplit = false;
    List<int[]> halfWorkIndex = shiftInfoBean.getHalfWorkIndex();
    if(halfWorkIndex != null && !halfWorkIndex.isEmpty()){
      int[] halfWorkIndexs = halfWorkIndex.get(0);
      if(halfWorkIndexs != null && halfWorkIndexs.length == 3){
        int flowMins = kqTimesArrayComInfo.getCnt(initArrays, flowbegintimeIndex, flowendtimeIndex, 1);
        if(flowMins > 0){
          int firstTimeIndex = halfWorkIndexs[0];//当天班次的最早时间 这个时间肯定不可能跨天的
          int middleTimeIndex = halfWorkIndexs[1];//当天班次的中间时间 这个时间可能会跨天
          int lastTimeIndex = halfWorkIndexs[2];//当天班次的最晚时间 这个时间也可能会跨天
          if(middleTimeIndex > flowbegintimeIndex && middleTimeIndex < flowendtimeIndex){
            int am_half = kqTimesArrayComInfo.getCnt(initArrays, flowbegintimeIndex, middleTimeIndex, 1);
            int pm_half = kqTimesArrayComInfo.getCnt(initArrays, middleTimeIndex, flowendtimeIndex, 1);
            if(am_half > 0 && pm_half > 0){
              splitBean.setFromTime(kqTimesArrayComInfo.getTimesByArrayindex(firstTimeIndex));
              splitBean.setToTime(kqTimesArrayComInfo.getTimesByArrayindex(lastTimeIndex));
              splitBean.setD_Mins(shiftInfoBean.getWorkmins()*1.0);
              splitBean.setDuration("1.0");
              isSplit = true;
            }else if(am_half > 0){
              splitBean.setFromTime(kqTimesArrayComInfo.getTimesByArrayindex(firstTimeIndex));
              splitBean.setToTime(kqTimesArrayComInfo.getTimesByArrayindex(middleTimeIndex));
              splitBean.setD_Mins((shiftInfoBean.getWorkmins()*1.0)/2.0);
              splitBean.setDuration("0.5");
              isSplit = true;
            }else if(pm_half > 0){
              splitBean.setFromTime(kqTimesArrayComInfo.getTimesByArrayindex(middleTimeIndex));
              splitBean.setToTime(kqTimesArrayComInfo.getTimesByArrayindex(lastTimeIndex));
              splitBean.setD_Mins((shiftInfoBean.getWorkmins()*1.0)/2.0);
              splitBean.setDuration("0.5");
              isSplit = true;
            }
          }else if(middleTimeIndex <= flowbegintimeIndex){
            splitBean.setFromTime(kqTimesArrayComInfo.getTimesByArrayindex(middleTimeIndex));
            splitBean.setToTime(kqTimesArrayComInfo.getTimesByArrayindex(lastTimeIndex));
            splitBean.setD_Mins((shiftInfoBean.getWorkmins()*1.0)/2.0);
            splitBean.setDuration("0.5");
            isSplit = true;
          }else if(middleTimeIndex >= flowendtimeIndex){
            splitBean.setFromTime(kqTimesArrayComInfo.getTimesByArrayindex(firstTimeIndex));
            splitBean.setToTime(kqTimesArrayComInfo.getTimesByArrayindex(middleTimeIndex));
            splitBean.setD_Mins((shiftInfoBean.getWorkmins()*1.0)/2.0);
            splitBean.setDuration("0.5");
            isSplit = true;
          }
        }
      }
    }
    return isSplit;
  }

  /**
   * 非工作日 根据半天来计算时长
   * @param kqTimesArrayComInfo
   * @param splitBean
   * @param flowbegintimeIndex
   * @param flowendtimeIndex
   */
  public static boolean getSplitDurationBean4NonTime(KQTimesArrayComInfo kqTimesArrayComInfo, SplitBean splitBean, int flowbegintimeIndex, int flowendtimeIndex) {
    int half_index = kqTimesArrayComInfo.getArrayindexByTimes(non_work_half_time);
    int flowMins = flowendtimeIndex - flowbegintimeIndex;
    flowMins = flowMins > 0 ? flowMins : 0;
    boolean isSplit = false;
    if(flowMins > 0){
      if(flowbegintimeIndex < half_index && flowendtimeIndex > half_index){
        splitBean.setFromTime(kqTimesArrayComInfo.getTimesByArrayindex(flowbegintimeIndex));
        splitBean.setToTime(kqTimesArrayComInfo.getTimesByArrayindex(flowendtimeIndex));
        splitBean.setD_Mins(splitBean.getWorkmins());
        splitBean.setDuration("1.0");
        isSplit = true;
      }else {
        splitBean.setFromTime(kqTimesArrayComInfo.getTimesByArrayindex(flowbegintimeIndex));
        splitBean.setToTime(kqTimesArrayComInfo.getTimesByArrayindex(flowendtimeIndex));
        splitBean.setD_Mins((splitBean.getWorkmins()*1.0)/2.0);
        splitBean.setDuration("0.5");
        isSplit = true;
      }
    }
    return isSplit;
  }

  /**
   * 根据下拉框来计算半天
   * @param splitBean
   */
  @Override
  public void getSplitDurationBean(SplitBean splitBean) throws Exception{

    SplitActionUtil splitActionUtil = new SplitActionUtil();
    String resourceid = splitBean.getResourceId();
    String fromDate = splitBean.getFromdatedb();
    String toDate = splitBean.getTodatedb();
    String fromTime = splitBean.getFromtimedb();
    String toTime = splitBean.getTotimedb();
    DurationTypeEnum durationTypeEnum = splitBean.getDurationTypeEnum();
    if(!(fromTime.equalsIgnoreCase(SplitSelectSet.forenoon_start) || fromTime.equalsIgnoreCase(SplitSelectSet.forenoon_end))){
      return;
    }
    if(!(toTime.equalsIgnoreCase(SplitSelectSet.afternoon_start) || toTime.equalsIgnoreCase(SplitSelectSet.afternoon_end))){
      return;
    }

    //获取对应人员和对应日期下的工作时段
    List<Map<String,String>> splitLists = SplitActionUtil.getSplitHalfDayList(fromDate,toDate,fromTime,toTime);

    if(!splitLists.isEmpty()) {
      KQTimesArrayComInfo arrayComInfo = new KQTimesArrayComInfo();

      for (int i = 0; i < splitLists.size(); i++) {
        Map<String, String> splitMap = splitLists.get(i);
        String splitDate = Util.null2String(splitMap.get("splitDate"));
        int foreOrAfter = Util.getIntValue(Util.null2String(splitMap.get("foreOrAfter")));
        ShiftInfoBean shiftInfoBean = KQDurationCalculatorUtil.getWorkTime(resourceid, splitDate,false);
        splitBean.setBelongDate(splitDate);
        boolean shouldLog = true;
        if(durationTypeEnum == DurationTypeEnum.COMMON_CAL){
          shouldLog = false;
        }
        if(shouldLog){
          kqLog.info("doSerialSplitList:"+ (splitBean != null ? JSON.toJSONString(splitBean):null));
        }

        if(shiftInfoBean != null){
          if(!shiftInfoBean.isIsfree()){
            //先计算下时长
            splitBean.setWorkmins(shiftInfoBean.getWorkmins());
            List<int[]> halfWorkIndex = shiftInfoBean.getHalfWorkIndex();
            List<int[]> shift_halfWorkIndex = Lists.newArrayList();
            if(!halfWorkIndex.isEmpty()){
              List<int[]> workLongTimeIndex = shiftInfoBean.getWorkLongTimeIndex();
              if(workLongTimeIndex.size() == 1){
//                根据个性化设置获取到真实的半天班次
                get_shift_halfWorkIndex_by_rule(shift_halfWorkIndex,shiftInfoBean,arrayComInfo,splitBean.getResourceId());
              }
              if(!shift_halfWorkIndex.isEmpty()){
                splitHalftoBean(splitBean,splitDate, foreOrAfter, shift_halfWorkIndex,arrayComInfo);
              }else{
                splitHalftoBean(splitBean,splitDate, foreOrAfter, halfWorkIndex,arrayComInfo);
              }
            }
          }else{
            int freeWorkMins = Util.getIntValue(shiftInfoBean.getFreeWorkMins());
            splitBean.setWorkmins(freeWorkMins);
            String freeSignStart = shiftInfoBean.getFreeSignStart();
            String freeSignMiddle = shiftInfoBean.getFreeSignMiddle();
            String freeSignEnd = shiftInfoBean.getFreeSignEnd();
            if(freeSignStart.length() > 0){
              List<int[]> halfWorkIndex = new ArrayList<>();
              int[] halfWorkIndexs = new int[3];
              halfWorkIndexs[0]=arrayComInfo.getArrayindexByTimes(freeSignStart);//当天班次的最早时间 这个时间肯定不可能跨天的
              halfWorkIndexs[1]=arrayComInfo.getArrayindexByTimes(freeSignMiddle);//当天班次的中间时间 这个时间可能会跨天
              halfWorkIndexs[2]=arrayComInfo.getArrayindexByTimes(freeSignEnd);//当天班次的最晚时间 这个时间也可能会跨天
              halfWorkIndex.add(halfWorkIndexs);
              splitHalftoBean(splitBean,splitDate, foreOrAfter, halfWorkIndex, arrayComInfo);
            }
          }
        }else{
          String computingMode = splitBean.getComputingMode();
          if("2".equalsIgnoreCase(computingMode)){
            String filterholidays = splitBean.getFilterholidays();
            boolean is_filterholidays = splitActionUtil.check_filterholidays(filterholidays,resourceid,splitDate,-1);
            if(is_filterholidays){
              continue;
            }
            splitNaturalHalf(splitBean,splitDate,foreOrAfter);
          }
        }
      }
    }
  }

  /**
   * 根据个性化设置获取到真实的半天班次
   * @param shift_halfWorkIndex
   * @param shiftInfoBean
   * @param arrayComInfo
   * @param resourceId
   */
  public void get_shift_halfWorkIndex_by_rule(List<int[]> shift_halfWorkIndex,
      ShiftInfoBean shiftInfoBean, KQTimesArrayComInfo arrayComInfo, String resourceId) throws Exception {
    boolean is_flow_humanized = KQSettingsBiz.is_flow_humanized();
    if(!is_flow_humanized){
      return ;
    }
    List<String> real_allLongWorkTime = Lists.newArrayList();
    List<String> allLongWorkTime = shiftInfoBean.getAllLongWorkTime();
    CollectionUtils.addAll(real_allLongWorkTime,new Object[allLongWorkTime.size()]);
    Collections.copy(real_allLongWorkTime, allLongWorkTime);
    List<String[]> real_workAcrossTime = Lists.newArrayList();
    List<String[]> workAcrossTime = shiftInfoBean.getWorkAcrossTime();
    //个性化设置只支持一次打卡的
    Map<String,String> shifRuleMap = Maps.newHashMap();
    KQShiftRuleInfoBiz.getShiftRuleInfo(shiftInfoBean,resourceId,shifRuleMap);
    if(!shifRuleMap.isEmpty()){
      if(shifRuleMap.containsKey("shift_beginworktime")){
        String shift_beginworktime = Util.null2String(shifRuleMap.get("shift_beginworktime"));
        if(shift_beginworktime.length() > 0){
          real_allLongWorkTime.set(0,shift_beginworktime);
        }
      }
      if(shifRuleMap.containsKey("shift_endworktime")){
        String shift_endworktime = Util.null2String(shifRuleMap.get("shift_endworktime"));
        if(shift_endworktime.length() > 0){
          real_allLongWorkTime.set(1,shift_endworktime);
        }
      }
      KQShiftRuleInfoBiz kqShiftRuleInfoBiz = new KQShiftRuleInfoBiz();
      kqShiftRuleInfoBiz.reset_halfIndex(shiftInfoBean, real_allLongWorkTime, arrayComInfo);
      shift_halfWorkIndex.addAll(shiftInfoBean.getHalfWorkIndex());
    }
  }

  /**
   * 针对非自然日半天的拆分
   * @param splitBean
   * @param splitDate
   * @param foreOrAfter
   */
  private void splitNaturalHalf(SplitBean splitBean,String splitDate,int foreOrAfter) {

    String fromDate = splitDate;
    String toDate = splitDate;
    String splitFromTime = "";
    String splitToTime = "";
    String duration = "";

    switch (foreOrAfter){
      case WorkHalfUnitSplitChain.fore_fore_index:
        splitFromTime = SplitSelectSet.forenoon_start;
        splitToTime = SplitSelectSet.forenoon_end;
        duration = "0.5";
        break;
      case WorkHalfUnitSplitChain.fore_after_index:
        splitFromTime = SplitSelectSet.forenoon_start;
        splitToTime = SplitSelectSet.afternoon_end;
        duration = "1.0";
        break;
      case WorkHalfUnitSplitChain.after_fore_index:
        break;
      case WorkHalfUnitSplitChain.after_after_index:
        splitFromTime = SplitSelectSet.afternoon_start;
        splitToTime = SplitSelectSet.afternoon_end;
        duration = "0.5";
        break;
      default:
        break;
    }
    splitBean.setFromDate(fromDate);
    splitBean.setFromTime(splitFromTime);
    splitBean.setToDate(toDate);
    splitBean.setToTime(splitToTime);
    splitBean.setDuration(duration);

    SplitBean newsplitBean = new SplitBean();
    //然后把bean重新赋值下，根据拆分后的时间
    BeanUtils.copyProperties(splitBean, newsplitBean);
    splitBeans.add(newsplitBean);
  }

  /**
   * 单独针对半天规则的 拆分流程数据
   * 理论上是需要先把半天的工作时段拆分
   * 根据拆分后的工作时段，再进行拆分
   * @param splitBean
   * @param splitDate
   * @param foreOrAfter
   * @param halfWorkIndex
   * @param arrayComInfo
   */
  private void splitHalftoBean(SplitBean splitBean,String splitDate,int foreOrAfter,List<int[]> halfWorkIndex,KQTimesArrayComInfo arrayComInfo){

    int[] halfWorkIndexs = halfWorkIndex.get(0);
    int firstTimeIndex = halfWorkIndexs[0];//当天班次的最早时间 这个时间肯定不可能跨天的
    int middleTimeIndex = halfWorkIndexs[1];//当天班次的中间时间 这个时间可能会跨天
    int lastTimeIndex = halfWorkIndexs[2];//当天班次的最晚时间 这个时间也可能会跨天

    DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    String fromDate = splitDate;
    String toDate = splitDate;
    String splitFromTime = "";
    String splitToTime = "";
    String duration = "";
    //跨天的话需要得到跨天的日期
    LocalDate localDateAcross = LocalDate.parse(splitDate).plusDays(1);
    int workmins = splitBean.getWorkmins();

    switch (foreOrAfter){
      case WorkHalfUnitSplitChain.fore_fore_index:
        splitFromTime = arrayComInfo.getTimesByArrayindex(firstTimeIndex);
        splitToTime = arrayComInfo.getTimesByArrayindex(middleTimeIndex);
        if(middleTimeIndex > 1439){
          toDate = localDateAcross.format(dateFormatter);
        }
        splitBean.setD_Mins(workmins/2);
        duration = "0.5";
        break;
      case WorkHalfUnitSplitChain.fore_after_index:
        splitFromTime = arrayComInfo.getTimesByArrayindex(firstTimeIndex);
        splitToTime = arrayComInfo.getTimesByArrayindex(lastTimeIndex);
        if(lastTimeIndex > 1439){
          toDate = localDateAcross.format(dateFormatter);
        }
        duration = "1.0";
        splitBean.setD_Mins(workmins);
        break;
      case WorkHalfUnitSplitChain.after_fore_index:
        break;
      case WorkHalfUnitSplitChain.after_after_index:
        splitFromTime = arrayComInfo.getTimesByArrayindex(middleTimeIndex);
        splitToTime = arrayComInfo.getTimesByArrayindex(lastTimeIndex);
        if(middleTimeIndex > 1439){
          fromDate = localDateAcross.format(dateFormatter);
        }
        if(lastTimeIndex > 1439){
          toDate = localDateAcross.format(dateFormatter);
        }
        duration = "0.5";
        splitBean.setD_Mins(workmins/2);
        break;
      default:
        break;
    }
    splitBean.setFromDate(fromDate);
    splitBean.setFromTime(splitFromTime);
    splitBean.setToDate(toDate);
    splitBean.setToTime(splitToTime);
    splitBean.setDuration(duration);

    SplitBean newsplitBean = new SplitBean();
    //然后把bean重新赋值下，根据拆分后的时间
    BeanUtils.copyProperties(splitBean, newsplitBean);
    splitBeans.add(newsplitBean);

  }

}
