package com.engine.kq.biz;
import com.engine.kq.bean.KQHrmScheduleSign;
import com.engine.kq.cmd.attendanceButton.ButtonStatusEnum;
import com.engine.kq.entity.KQGroupEntity;
import com.engine.kq.log.KQLog;
import com.engine.kq.util.KQDurationCalculatorUtil;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import weaver.common.DateUtil;
import weaver.conn.RecordSet;
import weaver.general.BaseBean;
import weaver.general.Util;
import weaver.hrm.User;
import weaver.hrm.resource.ResourceComInfo;
import weaver.systeminfo.SystemEnv;

/**
 * 获取签到签退按钮
 * 以及考勤流程数据
 * 以及上次签到时间
 */
public class KQSignDataFormat extends BaseBean{

  private KQLog kqLog = new KQLog();
  private String curDate = DateUtil.getCurrentDate();
  private DateTimeFormatter fullFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
  private DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm");
  private LocalDateTime now = LocalDateTime.now();
  private User user;
  private Map<String, Object> params = null;
	public KQSignDataFormat(Map<String, Object> params, User user) {
		this.user = user;
		this.params = params;
		this.curDate = Util.null2String(params.get("curDate"));
    this.now = (LocalDateTime)(params.get("now"));
	}

  /**
   * 一个完整的timelines里map的样子
   * {
     * across: "0" 是否是次日
     * active: "1" 是否是允许签到签退的范围
     * belongdate: "2018-12-27" 根据班次获取的所属日期
     * canSignTime: "2018-12-27 00:00:00" 允许签到签退的时间范围
     * date: "2018-12-27" 签到签退的日期
     * datetime: "2018-12-27 08:30:00" 签到签退日期+上下班时间
     * isYellow: "1" 当前时间是否已经是迟到或者早退
     * isacross: "0" 当前时间对应的班次是否是跨天班次
     * islastsign: "0" 是否是最后一次签退
     * min: "0" 允许打卡时段控制
     * needSign: "1" 是否可以签到签退，在active的基础上增加了hrmschedulesign签到签退数据的判断
     * pre: "0" 是否是昨日
     * serialid: "521" 班次id
     * signsection: "2018-12-27 00:00:00#2018-12-27 14:00:00" 允许签到签退的范围
     * time: "08:30" 上班时间/下班时间
     * type: "on" 对应的是签到还是签退的状态
     * workdatesection: "2018-12-27 08:30:00#2018-12-27 11:30:00" 上下班日期时段
     * worksection: "08:30-11:30" 上下班时间
   * }
   * @return
   */
  public Map<String, Object> execute() {
    Map<String, Object> retmap = new HashMap<String, Object>();
    RecordSet rs = new RecordSet();
    String sql = "";
    try{

      //真正的考勤时间线
      List<Object> timelineList = new ArrayList<>();
      DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");

      KQGroupMemberComInfo kqGroupMemberComInfo = new KQGroupMemberComInfo();
      KQGroupComInfo kqGroupComInfo = new KQGroupComInfo();
      ResourceComInfo resourceComInfo = new ResourceComInfo();
      KQReportBiz kqReportBiz = new KQReportBiz();

      String lastname = user.getLastname();
      String messagerurl = resourceComInfo.getMessagerUrls(""+user.getUID());
      String shortname = "";

      String ismobile = Util.null2String(params.get("ismobile"));

      boolean USERICONLASTNAME = Util.null2String(new BaseBean().getPropValue("Others" , "USERICONLASTNAME")).equals("1");
      if(USERICONLASTNAME&&(messagerurl.indexOf("icon_w_wev8.jpg")>-1||messagerurl.indexOf("icon_m_wev8.jpg")>-1||messagerurl.indexOf("dummyContact.png")>-1)){
        shortname = User.getLastname(Util.null2String(Util.formatMultiLang(lastname, ""+user.getLanguage())));
      }

      String groupname = "";
      String groupid = kqGroupMemberComInfo.getKQGroupId(user.getUID()+"");
      String outsidesign = "";
      KQGroupEntity kqGroupEntity = kqGroupMemberComInfo.getUserKQGroupInfo(user.getUID()+"");
      if (kqGroupEntity != null) {
        outsidesign = kqGroupEntity.getOutsidesign();
      }else{
        groupname = SystemEnv.getHtmlLabelName(10000799,weaver.general.Util.getIntValue(user.getLanguage()));
        retmap.put("showbutton", "0");
        retmap.put("status", "1");
        retmap.put("groupname", groupname);
        return retmap;
      }

      boolean isAdmin = user.isAdmin();
      if(isAdmin){
        retmap.put("showbutton", "0");
        retmap.put("status", "1");
        return retmap;
      }
//   * 1、PC和移动端均可打卡
//          * 2、仅PC可打卡
//          * 3、仅移动端可打卡
//          * 4、无需打卡
      String groupSignType = getSignType();
      //无需打卡
      if("4".equalsIgnoreCase(groupSignType)){
        retmap.put("showbutton", "0");
        retmap.put("status", "1");
        return retmap;
      }
      if("2".equalsIgnoreCase(groupSignType)){
        if("1".equalsIgnoreCase(ismobile)){
          retmap.put("showbutton", "0");
          retmap.put("status", "1");
          return retmap;
        }
      }
      if("3".equalsIgnoreCase(groupSignType)){
        if(!"1".equalsIgnoreCase(ismobile)){
          retmap.put("showbutton", "0");
          retmap.put("status", "1");
          return retmap;
        }
      }

      String yesterday = LocalDate.parse(curDate).minusDays(1).format(dateFormatter);
      List<Object> yesterdayLineButton = new ArrayList<>();
      List<Object> todayLineButton = new ArrayList<>();
      List<Object> restLineButton = new ArrayList<>();

      //弹性工作制
      List<Object> freeLineButton = new ArrayList<>();

      //先获取考勤工作时段的按钮 上下班时间
      Map<String, Object> todayLineMap = KQDurationCalculatorUtil.getWorkButton(user, curDate,true);
      boolean isfree = "1".equalsIgnoreCase(Util.null2String(todayLineMap.get("isfree")));

      if(isfree){
        do4FreeLine(user,freeLineButton,todayLineMap);
        if(freeLineButton != null && !freeLineButton.isEmpty()){
          timelineList.addAll(freeLineButton);
          retmap.put("lastname", lastname);
          retmap.put("shortname", shortname);
          retmap.put("messagerurl", messagerurl);
          retmap.put("groupname", groupname+SystemEnv.getHtmlLabelName(10000800,weaver.general.Util.getIntValue(user.getLanguage())));
          retmap.put("outsidesign", outsidesign);
          retmap.put("date", curDate);
          retmap.put("timeline", timelineList);
          retmap.put("status", "1");
          return retmap;
        }
      }
      //每次打开考勤按钮的时候，都只能有一个活动按钮
      List<String> activeList = new ArrayList<>();

      if(!todayLineMap.isEmpty()){
        if(todayLineMap.get("pre_timelineList") != null){
          do4YesterdayLine(todayLineMap,yesterdayLineButton,kqReportBiz,timelineList,yesterday,activeList);
        }
        if(todayLineMap.get("timelineList") != null){
          do4TodayLine(todayLineMap,todayLineButton,kqReportBiz,timelineList,activeList);
        }
      }else{
        //节假日或者休息日需要默认给客户拼接一个timelineList
        retmap.put("isrest", "1");
        do4RestLine(""+user.getUID(),restLineButton);
        timelineList.addAll(restLineButton);
      }





      if(groupid.length() > 0){
        groupname = SystemEnv.getHtmlLabelName(10000801,weaver.general.Util.getIntValue(user.getLanguage()))+kqGroupComInfo.getGroupname(groupid);
      }else{
        groupname = SystemEnv.getHtmlLabelName(10000799,weaver.general.Util.getIntValue(user.getLanguage()));
      }

      retmap.put("lastname", lastname);
      retmap.put("shortname", shortname);
      retmap.put("messagerurl", messagerurl);
      retmap.put("groupname", groupname);
      retmap.put("outsidesign", outsidesign);
      retmap.put("date", curDate);
      retmap.put("timeline", timelineList);
      retmap.put("status", "1");
    }catch (Exception e) {
      retmap.put("status", "-1");
      retmap.put("message",  SystemEnv.getHtmlLabelName(382661,user.getLanguage()));
      writeLog(e);
    }
    return retmap;
  }

  /**
   * 当日的考勤按钮处理
   * @param todayLineMap
   * @param todayLineButton
   * @param kqReportBiz
   * @param timelineList
   * @param activeList
   */
  private void do4TodayLine(Map<String, Object> todayLineMap, List<Object> todayLineButton,
      KQReportBiz kqReportBiz, List<Object> timelineList,
      List<String> activeList) {

    List<Object> todayLine = (List<Object>)todayLineMap.get("timelineList");
    if(todayLine != null && !todayLine.isEmpty()){
      getWorkTimeButton(false, todayLine,todayLineButton);
      //获取当天的考勤数据
//      List<Object> reports = kqReportBiz.getKqDateInfo(""+user.getUID(),curDate,curDate,true);
      List<Object> reports = new ArrayList<>();
      getSignButton(user.getUID()+"",todayLineButton,reports);
      timelineList.addAll(todayLineButton);
    }
  }

  /**
   * 昨日跨天的考勤按钮处理
   * @param yesterdayLineMap
   * @param yesterdayLineButton
   * @param kqReportBiz
   * @param timelineList
   * @param yesterday
   * @param activeList
   */
  private void do4YesterdayLine(Map<String, Object> yesterdayLineMap,
      List<Object> yesterdayLineButton, KQReportBiz kqReportBiz,
      List<Object> timelineList, String yesterday, List<String> activeList) {

    List<Object> yesterdayLine = (List<Object>)yesterdayLineMap.get("pre_timelineList");
    if(yesterdayLine != null && !yesterdayLine.isEmpty()){
      getWorkTimeButton(true, yesterdayLine,yesterdayLineButton);
      //获取前一天的考勤数据
//          List<Object> reports = kqReportBiz.getKqDateInfo(""+user.getUID(),yesterday,yesterday,true);
      List<Object> reports = new ArrayList<>();
      getSignButton(user.getUID()+"",yesterdayLineButton,reports);
      timelineList.addAll(yesterdayLineButton);
    }
  }

  /**
   * 针对自由工作制的人员单独处理
   * @param user
   * @param freeLineButton
   * @param todayLineMap
   */
  private void do4FreeLine(User user, List<Object> freeLineButton,
      Map<String, Object> todayLineMap) {
    String resourceId = ""+user.getUID();
    if(todayLineMap != null && !todayLineMap.isEmpty()){
      DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("HH:mm:ss");
      LocalTime curTime = LocalTime.now();

      String signStart = Util.null2String(todayLineMap.get("signStart"));//签到开始时间
      String workMins = Util.null2String(todayLineMap.get("workMins"));//工作时长
      LocalTime signStartLocal = LocalTime.parse(signStart+":00", dateTimeFormatter);
      boolean canSign = false;
      if(curTime.isAfter(signStartLocal)){
        canSign = true;
      }

      List<Object> signInList = new ArrayList<>();
      List<Object> signOutList = new ArrayList<>();

      KQScheduleSignBiz kqScheduleSignBiz = new KQScheduleSignBiz.KQScheduleSignParamBuilder().resourceidParam(resourceId)
          .userTypeParam(user.getLogintype()).signDateParam(curDate).build();
      List<KQHrmScheduleSign> kqHrmScheduleSigns = kqScheduleSignBiz.getFreeScheduleSignInfo();
      if(kqHrmScheduleSigns != null && !kqHrmScheduleSigns.isEmpty()) {
        for(KQHrmScheduleSign sign : kqHrmScheduleSigns){
          String signtype = sign.getSigntype();
          String signtime = sign.getSigntime();
          String signdate = sign.getSigndate();
          String signStatus = sign.getSignstatus();
          String addr = sign.getAddr();
          Map<String,Object> signWorkMapTmp = new HashMap<>();
          signWorkMapTmp.put("signtime", signtime);
          signWorkMapTmp.put("addr", addr);
          signWorkMapTmp.put("signdate", signdate);
          signWorkMapTmp.put("signStatus", signStatus);

          //签到
          if("1".equalsIgnoreCase(signtype)){
            signInList.add(signWorkMapTmp);
          }
          //签退
          if("2".equalsIgnoreCase(signtype)){
            signOutList.add(signWorkMapTmp);
          }
        }
        for(int i = 0 ; i <signInList.size() ;i++){
          Map<String,Object> signWorkMap = (Map<String, Object>) signInList.get(i);
          String signtime = Util.null2String(signWorkMap.get("signtime"));
          String addr = Util.null2String(signWorkMap.get("addr"));
          freeLineButton.add(reBuildFreeButton("on", curDate, "0", "0",signtime,addr));
        }

        for(int i = 0 ; i <signOutList.size() ;i++){
          Map<String,Object> signWorkMap = (Map<String, Object>) signOutList.get(i);
          String signtime = Util.null2String(signWorkMap.get("signtime"));
          String addr = Util.null2String(signWorkMap.get("addr"));
          freeLineButton.add(reBuildFreeButton("off", curDate, "0", "0",signtime,addr));
        }
        if(signInList.size() == signOutList.size()){
          //如果是成对存在的，那么需要再多出来俩，支持多次签到签退
          freeLineButton.add(reBuildFreeButton("on", curDate, "1", canSign?"1":"0","",""));
          freeLineButton.add(reBuildFreeButton("off", curDate, "0", "0","",""));
        }else{
          //如果不是成对存在，一定是签到多，签退少，当前处于需要签退的状态
          freeLineButton.add(reBuildFreeButton("off", curDate, "1", "1","",""));
        }

      }else{
        //如果没有考勤数据，那么就是先签到再签退
        freeLineButton.add(reBuildFreeButton("on", curDate, "1", canSign?"1":"0","",""));
        freeLineButton.add(reBuildFreeButton("off", curDate, "0", "0","",""));
      }
    }

  }

  private Map<String,Object> reBuildFreeButton(String type,String date,String active,String needSign,String signTime,String position){
    Map<String,Object> freetimelineMap = new HashMap<>();
    freetimelineMap.put("type", type);
    freetimelineMap.put("belongdate", date);
    freetimelineMap.put("date", date);
    freetimelineMap.put("active", active);
    freetimelineMap.put("needSign", needSign);
    freetimelineMap.put("signTime", signTime);
    freetimelineMap.put("position", position);
    freetimelineMap.put("time", "");
    freetimelineMap.put("isfree", "1");

    return freetimelineMap;
  }

  /**
   * 真对非工作时间的签到签退
   * @param resourceId
   * @param restLineButton
   */
  private void do4RestLine(String resourceId, List<Object> restLineButton) {
    boolean hasSignIn = false;
    boolean hasSignOut = false;
    boolean isActive = true;
    Map<String,Object> timelineOnMap = new HashMap<>();
    timelineOnMap.put("type", "on");
    timelineOnMap.put("time", "");
    timelineOnMap.put("belongdate", curDate);
    timelineOnMap.put("date", curDate);
    Map<String,Object> timelineOffMap = new HashMap<>();
    timelineOffMap.put("type", "off");
    timelineOffMap.put("time", "");
    timelineOffMap.put("belongdate", curDate);
    timelineOffMap.put("date", curDate);

    KQScheduleSignBiz kqScheduleSignBiz = new KQScheduleSignBiz.KQScheduleSignParamBuilder().resourceidParam(resourceId)
        .userTypeParam(user.getLogintype()).signDateParam(curDate).build();
    Map<String,KQHrmScheduleSign> signMap = kqScheduleSignBiz.getScheduleSignInfo();
    if(signMap != null && !signMap.isEmpty()) {
      KQHrmScheduleSign signInTimeBean = signMap.get("signin");
      KQHrmScheduleSign signOutTimeBean =  signMap.get("signout");
      if(signInTimeBean != null){
        String signtimeTmp = Util.null2String(signInTimeBean.getSigntime());
        timelineOnMap.put("signTime", signtimeTmp);
        timelineOnMap.put("position", Util.null2String(signInTimeBean.getAddr()));
        hasSignIn = true;
      }
      if(signOutTimeBean != null){
        String signtimeTmp = Util.null2String(signOutTimeBean.getSigntime());
        timelineOffMap.put("signTime", signtimeTmp);
        timelineOffMap.put("position", Util.null2String(signOutTimeBean.getAddr()));
        hasSignOut = true;
      }
      if(hasSignIn){
        //有签到 就记录下
        timelineOffMap.put("signInTime4Out", timelineOnMap.get("signTime"));
      }
    }
    getActiveSign(isActive, hasSignIn, hasSignOut, timelineOnMap, timelineOffMap);
    restLineButton.add(timelineOnMap);
    restLineButton.add(timelineOffMap);
  }

  /**
   * 获取考勤组的考勤方式
   * 1、PC和移动端均可打卡
   * 2、仅PC可打卡
   * 3、仅移动端可打卡
   */
  private String getSignType() {
    KQGroupMemberComInfo kqGroupMemberComInfo = new KQGroupMemberComInfo();
    KQGroupEntity kqGroupEntity = kqGroupMemberComInfo.getUserKQGroupInfo(user.getUID()+"");
    if(kqGroupEntity == null){
      return "";
    }
    return kqGroupEntity != null ? kqGroupEntity.getSignintype(): "";
  }

  /**
   * 根据工作时段来获取对应工作时段下的签到签退数据
   * @param resourceId
   * @param timelineList
   * @param reports
   */
  private void getSignButton(String resourceId,List<Object> timelineList,List<Object> reports) {
    if(!timelineList.isEmpty()){
      //获取当前时间
      LocalDateTime now = LocalDateTime.now();

      //因为工作时段是成对存在的，所以timelineList一定是两两一对的复数[0,1] [2,3] [4,5]
      int count = timelineList.size();

      int workCnt = 0;
      for(int i = 0 ; i < count ; ){
        //成对出现的上下班时间
        int on_i = i;
        int off_i = i+1;
        Map<String,Object> timelineOnMap = (Map<String,Object>)timelineList.get(on_i);
        Map<String,Object> timelineOffMap = (Map<String,Object>)timelineList.get(off_i);
        if(timelineOnMap != null && !timelineOnMap.isEmpty() && timelineOffMap != null && !timelineOffMap.isEmpty()){
          String onTime = Util.null2String(timelineOnMap.get("time"));
          String belongdate = Util.null2String(timelineOnMap.get("belongdate"));
          String onSignSectionTime = Util.null2String(timelineOnMap.get("signSectionTime"));
          String onDateTime = Util.null2String(timelineOnMap.get("datetime"));
          String onIsacross = Util.null2String(timelineOnMap.get("isacross"));

          String offTime = Util.null2String(timelineOffMap.get("time"));
          String offSignSectionTime = Util.null2String(timelineOffMap.get("signSectionTime"));
          String offDateTime = Util.null2String(timelineOffMap.get("datetime"));
          String offIsacross = Util.null2String(timelineOffMap.get("isacross"));

          LocalDateTime onLocalDateTime = LocalDateTime.parse(onSignSectionTime,fullFormatter);
          LocalDateTime offLocalDateTime = LocalDateTime.parse(offSignSectionTime,fullFormatter);

          LocalDateTime onworkDateTime = LocalDateTime.parse(onDateTime,fullFormatter);
          LocalDateTime offworkDateTime = LocalDateTime.parse(offDateTime,fullFormatter);

          if("1".equalsIgnoreCase(onIsacross)){
            onTime = new KQTimesArrayComInfo().turn24to48Time(onTime);
            timelineOffMap.put("belongtime", onTime);
          }
          if("1".equalsIgnoreCase(offIsacross)){
            offTime = new KQTimesArrayComInfo().turn24to48Time(offTime);
            timelineOffMap.put("belongtime", offTime);
          }
          String worksection = onTime+"-"+offTime;

          if(i == (count-2)){
            //如果当前工作时段是最后一个工作时段
            timelineOnMap.put("islastsign", "1");
            timelineOffMap.put("islastsign", "1");
          }else{
            timelineOnMap.put("islastsign", "0");
            timelineOffMap.put("islastsign", "0");
          }

          boolean hasSignIn = false;
          boolean hasSignOut = false;
          boolean isActive = false;

          if((now.isAfter(onLocalDateTime) && now.isBefore(offLocalDateTime))||(now.isEqual(onLocalDateTime))||(now.isEqual(offLocalDateTime))){
            isActive = true;
          }
          if(now.isAfter(onworkDateTime)){
            timelineOnMap.put("isYellow", "1");
          }else{
            timelineOnMap.put("isYellow", "0");
          }
          if(now.isBefore(offworkDateTime)){
            timelineOffMap.put("isYellow", "1");
          }else{
            timelineOffMap.put("isYellow", "0");
          }
          if(onSignSectionTime.length() == 0 || offSignSectionTime.length() == 0){
            timelineOnMap.put("active", "0");
            timelineOffMap.put("active", "0");
            timelineOnMap.put("needSign", "0");
            timelineOffMap.put("needSign", "0");
            kqLog.info("考勤按钮报错："+user.getLastname()+"::"+curDate+":onSignSectionTime:"+onSignSectionTime+":offSignSectionTime:"+offSignSectionTime);
            return ;
          }
          String signDateTimeSql = buildSignSql(onSignSectionTime,offSignSectionTime);

          KQScheduleSignBiz kqScheduleSignBiz = new KQScheduleSignBiz.KQScheduleSignParamBuilder().resourceidParam(resourceId)
              .userTypeParam(user.getLogintype()).signDateTimeSqlParam(signDateTimeSql).build();
          Map<String,KQHrmScheduleSign> signMap = kqScheduleSignBiz.getScheduleSignInfo();
          if(signMap != null && !signMap.isEmpty()){
            KQHrmScheduleSign signInTimeBean = signMap.get("signin");
            KQHrmScheduleSign signOutTimeBean =  signMap.get("signout");
            if(signInTimeBean != null){
              String signdate = Util.null2String(signInTimeBean.getSigndate());
              String signtimeTmp = Util.null2String(signInTimeBean.getSigntime());
              timelineOnMap.put("signbelong", "today");
              timelineOnMap.put("signbelongspan", SystemEnv.getHtmlLabelName(15537, user.getLanguage()));
              if(signdate.compareTo(curDate) < 0){
                timelineOnMap.put("signbelong", "yesterday");
                timelineOnMap.put("signbelongspan", SystemEnv.getHtmlLabelName(82640, user.getLanguage()));
              }
              timelineOnMap.put("signTime", signtimeTmp);
              timelineOnMap.put("position", Util.null2String(signInTimeBean.getAddr()));
              hasSignIn = true;
            }
            if(signOutTimeBean != null){
              String signdate = Util.null2String(signOutTimeBean.getSigndate());
              String signtimeTmp = Util.null2String(signOutTimeBean.getSigntime());
              timelineOffMap.put("signbelong", SystemEnv.getHtmlLabelName(15537, user.getLanguage()));
              timelineOffMap.put("signbelongspan", SystemEnv.getHtmlLabelName(15537, user.getLanguage()));
              if(signdate.compareTo(curDate) < 0){
                timelineOffMap.put("signbelong", SystemEnv.getHtmlLabelName(82640, user.getLanguage()));
                timelineOffMap.put("signbelongspan", SystemEnv.getHtmlLabelName(82640, user.getLanguage()));
              }
              timelineOffMap.put("signTime", signtimeTmp);
              timelineOffMap.put("position", Util.null2String(signOutTimeBean.getAddr()));
              hasSignOut = true;
            }
          }
          //根据考勤工作时段获取相应时段下的签到签退数据
          if(!reports.isEmpty()){
            updateStatusByReport(reports,belongdate, timelineOnMap, timelineOffMap,worksection);
          }
          getActiveSign(isActive, hasSignIn, hasSignOut, timelineOnMap, timelineOffMap);
        }

        i = i + 2;
        workCnt++;
      }
    }

  }

  /**
   * 根据考勤范围生成要查询的考勤表
   * @param onSignSectionTime
   * @param offSignSectionTime
   * @return
   */
  private String buildSignSql(String onSignSectionTime, String offSignSectionTime) {
    RecordSet rs = new RecordSet();
    StringBuffer sql = new StringBuffer();
    if(rs.getDBType().equals("oracle")||rs.getDBType().equals("postgresql")){
      sql.append(" AND signDate||' '||signTime>='").append(onSignSectionTime).append("' ");
      sql.append(" AND signDate||' '||signTime<='").append(offSignSectionTime).append("' ");
    }else if(rs.getDBType().equals("mysql")){
      sql.append(" AND concat(signDate,' ',signTime)>='").append(onSignSectionTime).append("' ");
      sql.append(" AND concat(signDate,' ',signTime)<='").append(offSignSectionTime).append("' ");
    }else{
      sql.append(" AND signDate+' '+signTime>='").append(onSignSectionTime).append("' ");
      sql.append(" AND signDate+' '+signTime<='").append(offSignSectionTime).append("' ");
    }
    return sql.toString();
  }

  /**
   * 根据考勤报表数据，更新打卡界面状态
   * @param reports
   * @param belongdate
   * @param timelineOnMap
   * @param timelineOffMap
   * @param worksection
   */
  public void updateStatusByReport(List<Object> reports, String belongdate,
      Map<String, Object> timelineOnMap,
      Map<String, Object> timelineOffMap, String worksection) {
    List<Object> checkInfoList = new ArrayList<>();
    for(int i = 0 ; i < reports.size() ; i++){
      Map<String, Object> reportData = (Map<String, Object>) reports.get(i);
      if(reportData != null && !reportData.isEmpty()){
        String kqdate = Util.null2String(reportData.get("kqdate"));
        if(belongdate.equalsIgnoreCase(kqdate)){
          checkInfoList = (List<Object>) reportData.get("checkInfo");
          if(checkInfoList != null && !checkInfoList.isEmpty()){
            for(int j = 0 ; j < checkInfoList.size() ; j++){
              Map<String, Object> kqData = (Map<String, Object>) checkInfoList.get(j);
              String workbegintime = Util.null2String(kqData.get("workbegintime"));
              String workendtime = Util.null2String(kqData.get("workendtime"));
              if(worksection.equalsIgnoreCase((workbegintime+"-"+workendtime))){
                //如果有考勤数据，再根据考勤数据同步更新下
                setStatusByReport(kqData,timelineOnMap,timelineOffMap);
                break;
              }
            }
          }
        }
      }
    }

  }

  /**
   * 根据考勤报表数据返回签到签退按钮状态
   * @param reportData
   * @param timelineOnMap
   * @param timelineOffMap
   */
  private void setStatusByReport(Map<String, Object> reportData, Map<String, Object> timelineOnMap, Map<String, Object> timelineOffMap) {

    String status = Util.null2String(reportData.get("status"));
    if(status.contains(ButtonStatusEnum.ABSENT.getStatusCode())){
      //旷工 旷工大于一切
      timelineOnMap.put("status", ButtonStatusEnum.ABSENT.getStatusCode());
      timelineOffMap.put("status", ButtonStatusEnum.ABSENT.getStatusCode());
      return ;
    }
    if(status.contains(ButtonStatusEnum.NORMAL.getStatusCode())){
      timelineOnMap.put("status", ButtonStatusEnum.NORMAL.getStatusCode());
      timelineOffMap.put("status", ButtonStatusEnum.NORMAL.getStatusCode());
      return ;
    }

    if(status.contains(ButtonStatusEnum.BELATE.getStatusCode())){
      //迟到
      timelineOnMap.put("status", ButtonStatusEnum.BELATE.getStatusCode());
    }
    if(status.contains(ButtonStatusEnum.LEAVEERALY.getStatusCode())){
      //早退
      timelineOffMap.put("status", ButtonStatusEnum.LEAVEERALY.getStatusCode());
    }
    if(status.contains(ButtonStatusEnum.NOSIGN.getStatusCode())){
      //漏签
      timelineOffMap.put("status", ButtonStatusEnum.NOSIGN.getStatusCode());
    }
  }

  /**
   * 生成时间轴上 需要签到和活动考勤点的标识
   * @param isActive
   * @param hasSignIn
   * @param hasSignOut
   * @param timelineOnMap
   * @param timelineOffMap
   */
  private void getActiveSign(boolean isActive,boolean hasSignIn,boolean hasSignOut,Map<String,Object> timelineOnMap,Map<String,Object> timelineOffMap) {

    if(isActive){
      if(hasSignIn){
        if(hasSignOut){
          //签到了，签退了
          timelineOnMap.put("active", "0");
          timelineOffMap.put("active", "0");

          timelineOnMap.put("needSign", "0");
          timelineOffMap.put("needSign", "0");
          timelineOffMap.put("reSign", "1");

        }else{
          //签到了，未签退
          timelineOnMap.put("active", "0");
          timelineOffMap.put("active", "1");

          timelineOnMap.put("needSign", "0");
          timelineOffMap.put("needSign", "1");

        }
      }else{
        if(hasSignOut){
          //未签到，签退了  理论上是不可能的

        }else{
          //未签到未签退
          timelineOnMap.put("active", "1");
          timelineOffMap.put("active", "0");

          timelineOnMap.put("needSign", "1");
          timelineOffMap.put("needSign", "0");

        }
      }

    }else{
      //如果都不在考勤范围内肯定不能签到签退
      timelineOnMap.put("active", "0");
      timelineOffMap.put("active", "0");

      timelineOnMap.put("needSign", "0");
      timelineOffMap.put("needSign", "0");

    }
  }

  /**
   * 先根据工作时段把考勤timeline基本信息加载一下
   * @param isYesterday
   * @param timeLine
   * @param timeLineButton
   */
  private void getWorkTimeButton(boolean isYesterday, List<Object> timeLine,
      List<Object> timeLineButton) {

    DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    String yesterday = LocalDate.parse(curDate).minusDays(1).format(dateFormatter);
    String nextday = LocalDate.parse(curDate).plusDays(1).format(dateFormatter);

    for(int i = 0 ; i < timeLine.size() ;){
      Map<String,Object> onTimelineMap = (Map<String,Object>)timeLine.get(i);
      Map<String,Object> offTimelineMap = (Map<String,Object>)timeLine.get(i+1);
      if(isYesterday){
        Map<String,Object> onTimelineMapTmp = reBuildYesTimeMap(onTimelineMap,yesterday,"on");
        Map<String,Object> offTimelineMapTmp = reBuildYesTimeMap(offTimelineMap,yesterday,"off");
        //如果允许打卡时间也跨天，那么也需要显示出来按钮
        if(Util.null2String(offTimelineMapTmp.get("signAcross")).equalsIgnoreCase("1")){
          timeLineButton.add(onTimelineMapTmp);
          timeLineButton.add(offTimelineMapTmp);
        }
      }else{
        Map<String,Object> onTimelineMapTmp = reBuildTimeMap(onTimelineMap,nextday,"on");
        Map<String,Object> offTimelineMapTmp = reBuildTimeMap(offTimelineMap,nextday,"off");
        timeLineButton.add(onTimelineMapTmp);
        timeLineButton.add(offTimelineMapTmp);
      }
      i = i + 2;
    }

  }

  /**
   * 针对前一天的工作时间 根据跨天判断重构一遍数据
   * @param timelineMap
   * @param yesterday
   * @param isOnOff
   */
  private Map<String,Object> reBuildYesTimeMap(Map<String, Object> timelineMap, String yesterday,
      String isOnOff) {

    Map<String,Object> lineMap = new HashMap<>();

    String isacross = Util.null2String(timelineMap.get("isacross"));
    String min = Util.null2String(timelineMap.get("min"));
    String time = Util.null2String(timelineMap.get("time"));
    String workmins = Util.null2String(timelineMap.get("workmins"));
//    打卡时段设置 一定是要开启的
    String isPunchOpen = "1";
    String signAcross = Util.null2String(timelineMap.get("signAcross"));
    int tMin = Util.getIntValue(min,0);

    lineMap.put("type", timelineMap.get("type"));
    lineMap.put("serialid", timelineMap.get("serialid"));
    lineMap.put("isacross", isacross);
    lineMap.put("time", time);
    lineMap.put("belongtime", time);
    lineMap.put("min", min);
    lineMap.put("workmins", workmins);
    lineMap.put("isPunchOpen", isPunchOpen);
    lineMap.put("signAcross", signAcross);

    if("on".equalsIgnoreCase(isOnOff)){
      if("1".equalsIgnoreCase(isacross)){
        //上班时间，跨天
        lineMap.put("date", curDate);//打卡日期
        lineMap.put("belongdate", yesterday);//工作时段所属日期
        lineMap.put("pre", "0");//是否是昨日
        lineMap.put("across", "0");//是否是次日
        lineMap.put("datetime", curDate+" "+time+":00");//应打卡日期+时间

        String canSignTime = curDate + " "+ time + ":00";
        if(tMin > 0) {
          LocalDateTime tmpLocalDateTime = LocalDateTime.parse(canSignTime, fullFormatter).minusMinutes(tMin);
          lineMap.put("signSectionTime",tmpLocalDateTime.format(fullFormatter));
          lineMap.put("canSignTime",tmpLocalDateTime.toLocalTime().format(timeFormatter));
        }
      }else{
        //上班时间，不跨天
        lineMap.put("date", curDate);
        lineMap.put("belongdate", yesterday);
        lineMap.put("pre", "1");
        lineMap.put("across", "0");
        lineMap.put("datetime", yesterday+" "+time+":00");//应打卡日期+时间
        String canSignTime = yesterday + " "+ time + ":00";

        if(tMin > 0) {
          LocalDateTime tmpLocalDateTime = LocalDateTime.parse(canSignTime, fullFormatter).minusMinutes(tMin);
          lineMap.put("signSectionTime",tmpLocalDateTime.format(fullFormatter));
          lineMap.put("canSignTime",tmpLocalDateTime.toLocalTime().format(timeFormatter));
        }
      }
    }else{
      if("1".equalsIgnoreCase(isacross)){
        //下班时间，跨天
        lineMap.put("date", curDate);
        lineMap.put("belongdate", yesterday);
        lineMap.put("pre", "0");
        lineMap.put("across", "0");
        lineMap.put("datetime", curDate+" "+time+":00");//应打卡日期+时间
        String canSignTime = curDate + " "+ time + ":00";
        if(tMin > 0) {
          LocalDateTime tmpLocalDateTime = LocalDateTime.parse(canSignTime, fullFormatter).plusMinutes(tMin);
          lineMap.put("signSectionTime",tmpLocalDateTime.format(fullFormatter));
          lineMap.put("canSignTime",tmpLocalDateTime.toLocalTime().format(timeFormatter));
        }
      }else{
        //下班时间，不跨天
        lineMap.put("date", curDate);
        lineMap.put("belongdate", yesterday);
        lineMap.put("pre", "1");
        lineMap.put("across", "0");
        lineMap.put("datetime", yesterday+" "+time+":00");//应打卡日期+时间
        String canSignTime = yesterday + " "+ time + ":00";
        //如果开启了打卡时段设置
        if(tMin > 0){
          LocalDateTime tmpLocalDateTime = LocalDateTime.parse(canSignTime, fullFormatter).plusMinutes(tMin);
          lineMap.put("signSectionTime",tmpLocalDateTime.format(fullFormatter));
          lineMap.put("canSignTime",tmpLocalDateTime.toLocalTime().format(timeFormatter));
        }
      }

    }
    return lineMap;
  }

  /**
   * 针对今天的工作时间 根据跨天判断重构一遍数据
   * @param timelineMap
   * @param nextday
   * @param isOnOff
   */
  private Map<String,Object> reBuildTimeMap(Map<String, Object> timelineMap, String nextday,
      String isOnOff) {
    Map<String,Object> lineMap = new HashMap<>();

    String isacross = Util.null2String(timelineMap.get("isacross"));
    String min = Util.null2String(timelineMap.get("min"));
    String time = Util.null2String(timelineMap.get("time"));
    String workmins = Util.null2String(timelineMap.get("workmins"));
//    打卡时段设置 一定是要开启的
    String isPunchOpen = "1";
    String signAcross = Util.null2String(timelineMap.get("signAcross"));
    int tMin = Util.getIntValue(min,0);

    lineMap.put("type", timelineMap.get("type"));
    lineMap.put("serialid", timelineMap.get("serialid"));
    lineMap.put("isacross", isacross);
    lineMap.put("time", time);
    lineMap.put("belongtime", time);
    lineMap.put("min", min);
    lineMap.put("workmins", workmins);
    lineMap.put("isPunchOpen", isPunchOpen);
    lineMap.put("signAcross", signAcross);

    if("on".equalsIgnoreCase(isOnOff)){
      if("1".equalsIgnoreCase(isacross)){
        //上班时间，跨天
        lineMap.put("date", curDate);
        lineMap.put("belongdate", curDate);
        lineMap.put("pre", "0");
        lineMap.put("across", "1");
        lineMap.put("datetime", nextday+" "+time+":00");//应打卡日期+时间
        String canSignTime = nextday + " "+ time + ":00";
        //如果开启了打卡时段设置
        if(tMin > 0){
          LocalDateTime tmpLocalDateTime = LocalDateTime.parse(canSignTime, fullFormatter).minusMinutes(tMin);
          lineMap.put("signSectionTime",tmpLocalDateTime.format(fullFormatter));
          lineMap.put("canSignTime",tmpLocalDateTime.toLocalTime().format(timeFormatter));
        }
      }else{
        //上班时间，不跨天
        lineMap.put("date", curDate);
        lineMap.put("belongdate", curDate);
        lineMap.put("pre", "0");
        lineMap.put("across", "0");
        lineMap.put("datetime", curDate+" "+time+":00");//应打卡日期+时间
        String canSignTime = curDate + " "+ time + ":00";
        if(tMin > 0){
          LocalDateTime tmpLocalDateTime = LocalDateTime.parse(canSignTime, fullFormatter).minusMinutes(tMin);
          lineMap.put("signSectionTime",tmpLocalDateTime.format(fullFormatter));
          lineMap.put("canSignTime",tmpLocalDateTime.toLocalTime().format(timeFormatter));
        }
      }
    }else{
      if("1".equalsIgnoreCase(isacross)){
        //下班时间，跨天
        lineMap.put("date", nextday);
        lineMap.put("belongdate", curDate);
        lineMap.put("pre", "0");
        lineMap.put("across", "1");
        lineMap.put("datetime", nextday+" "+time+":00");//应打卡日期+时间
        String canSignTime = nextday + " "+ time + ":00";
        if(tMin > 0){
          LocalDateTime tmpLocalDateTime = LocalDateTime.parse(canSignTime, fullFormatter).plusMinutes(tMin);
          lineMap.put("signSectionTime",tmpLocalDateTime.format(fullFormatter));
          lineMap.put("canSignTime",tmpLocalDateTime.toLocalTime().format(timeFormatter));
        }
      }else{
        //下班时间，不跨天
        lineMap.put("date", curDate);
        lineMap.put("belongdate", curDate);
        lineMap.put("pre", "0");
        lineMap.put("across", "0");
        lineMap.put("datetime", curDate+" "+time+":00");//应打卡日期+时间
        String canSignTime = curDate + " "+ time + ":00";
        if(tMin > 0){
          LocalDateTime tmpLocalDateTime = LocalDateTime.parse(canSignTime, fullFormatter).plusMinutes(tMin);
          lineMap.put("signSectionTime",tmpLocalDateTime.format(fullFormatter));
          lineMap.put("canSignTime",tmpLocalDateTime.toLocalTime().format(timeFormatter));
        }
      }

    }
    return lineMap;
  }

}
