package com.engine.attendance.attendanceanalysis.service.impl;

import com.engine.attendance.attendanceanalysis.cmd.ComputeAttendanceDurationCmd;
import com.engine.attendance.attendanceanalysis.cmd.GetClockInPointCmd;
import com.engine.attendance.attendanceanalysis.cmd.GetClockInTimeItemCmd;
import com.engine.attendance.attendanceanalysis.cmd.RecordDataCmd;
import com.engine.attendance.attendanceanalysis.service.UtilService;
import com.engine.attendance.component.persongroup.service.SchedulingResultsService;
import com.engine.attendance.component.persongroup.service.impl.SchedulingResultsServiceImpl;
import com.engine.attendance.enums.*;
import com.engine.common.cmd.GetDateCmd;
import com.engine.common.util.DateUtil;
import com.engine.common.util.DbTools;
import com.engine.common.util.ServiceUtil;
import com.engine.common.util.Utils;
import com.engine.core.impl.Service;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import weaver.general.Util;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
public class UtilServiceImpl extends Service implements UtilService {
    private SchedulingResultsService schedulingResultsService = ServiceUtil.getService(SchedulingResultsServiceImpl.class);

    /**
     * 获取人员班次信息
     * @param params
     * @return
     */
    @Override
    public Map<String, Object> getSchedulingInFormation(Map<String, Object> params) {

        /** 班次信息*/
        Map<String,Object> schedulingResultsMap = schedulingResultsService.queryDataTable(params);
        List<Map<String,Object>> schedulingResultsList = (List<Map<String,Object>>)schedulingResultsMap.get("data");
        schedulingResultsList = Utils.getSchedulingList(schedulingResultsList);
        Map<String,Object> schedulMap = Maps.newHashMap();
        String glpb = "";
        if (schedulingResultsList.size() >0){
            glpb = Util.null2String(schedulingResultsList.get(0).get("pbgl"));
        }
        //schedulingResultsList = schedulingResultsList.stream().filter(e -> !"1".equals(e.get("sfxx"))).collect(Collectors.toList());
      //  Map<String,String> schedulingMap = schedulingResultsList.stream().collect(Collectors.toMap(e-> Util.null2String(e.get("bcxx")).split("-")[0], e->Util.null2String(e.get("bcrq"))+"&"+Util.null2String(e.get("rqlx"))));
        Map<String,List<Map<String,Object>>> schedulingMap = schedulingResultsList.stream().collect(Collectors.groupingBy(e-> Util.null2String(e.get("bcxx")).split("-")[0]));
        Map<String,List<Map<String,Object>>> schedulingMapBydate = schedulingResultsList.stream().collect(Collectors.groupingBy(e-> Util.null2String(e.get("bcrq"))));
        schedulMap.put("schedulingMapBydate",schedulingMapBydate);

        Map<String,List<Map<String,Object>>> resultMap = Maps.newHashMap();
        String sql = "select a.id bcxx,a.edsc,a.zgzsc,a.bcsdxx,a.sfdx,a.sfkt,b.bdlx,a.btgz,a.fgsjd,a.zddxfz,a.dxhs,b.kssj dtkssj,b.jssj dtjssj,b.ksdk,b.jsdk,b.tqdkfzs,b.thdkfzs,b.edxss,b.sfdx dtsfdx,b.zddxfz dtzddxfz,b.dxhs dtdxhs from uf_jcl_kq_bcxx a left join uf_jcl_kq_bcxx_dt1 b on a.id=b.mainid where a.id in (";
        String bcxxIds = "";
        for (Map.Entry<String,List<Map<String,Object>>> entry :schedulingMap.entrySet()){
            if (!entry.getKey().equals("")){
                bcxxIds +=entry.getKey() +",";
            }
        }
        List<Map<String,Object>> dataList = Lists.newArrayList();
        if (!"".equals(bcxxIds)){
            bcxxIds = bcxxIds.substring(0,bcxxIds.length()-1);
            sql = sql +bcxxIds+") order by b.kssj";
            dataList = DbTools.getSqlToList(sql);
            Map<String,List<Map<String,Object>>> dataMap = dataList.stream().collect(Collectors.groupingBy(e->Util.null2String(e.get("bcxx"))));

            dataMap.entrySet().forEach(e -> {
                List<Map<String,Object>> schedulingList = schedulingMap.get(e.getKey());
                List<Map<String,Object>> bcxxs = e.getValue();
                for (Map<String,Object> scheduling :schedulingList){
                    String bcrq = Util.null2String(scheduling.get("bcrq"));
                    String rqlx = Util.null2String(scheduling.get("rqlx"));
                    String sfxx = Util.null2String(scheduling.get("sfxx"));
                    List<Map<String,Object>> classs = Lists.newArrayList();
                    for (Map<String,Object> map:bcxxs){
                        Map<String,Object> newMap = Maps.newHashMap();
                        newMap.putAll(map);
                        newMap.put("rqlx",rqlx);
                        newMap.put("sfxx",sfxx);
                        classs.add(newMap);
                    }
                    resultMap.put(bcrq,classs);
                }
            });
        }

        /** 加班计划*/
        sql = "select b.jbry,b.ksrq,b.kssj,a.jblx,b.jsrq,b.jssj,b.jbsc from uf_jcl_kq_jbjh a left join uf_jcl_kq_jbjh_dt1 b on a.id=b.mainid where b.jbry =? and b.ksrq>=? and b.ksrq<=? and (b.jbcx=0 or b.jbcx is null)";
        Map<String,List<Map<String,Object>>> overtimePlanMap = DbTools.getSqlToList(sql,params.get("pbdx"),params.get("startDate"),params.get("endDate")).stream().collect(Collectors.groupingBy(e -> Util.null2String(e.get("ksrq"))));

        //考勤项目

        List<Map<String,Object>> attendanceItems = (List<Map<String,Object>>)params.get("attendanceItems");
        //日期集合
        Map<String,Object> dateParam = Maps.newHashMap();
        dateParam.put("nd",Util.null2String(params.get("startDate")).split("-")[0]);
        dateParam.put("glpb",glpb);
        Map<String,Object> result = commandExecutor.execute(new GetDateCmd(dateParam));
        List<Map<String,Object>> list = (List<Map<String,Object>>)result.get("data");
        Map<String,String> dateMap = list.stream().collect(Collectors.toMap(e->Util.null2String(e.get("rq")),e->Util.null2String(e.get("rqlx"))));


        for (Map.Entry<String,List<Map<String,Object>>> e: overtimePlanMap.entrySet()){
            if (resultMap.get(e.getKey()) == null){
                resultMap.put(e.getKey(),Lists.newArrayList());
            }
            List<Map<String,Object>> resultList = resultMap.get(e.getKey());
            List<Map<String,Object>> schedulingdateMap = schedulingMapBydate.get(e.getKey());
            Map<String,Object> overtimePlan = e.getValue().get(0);


            Map<String,Object> map = Maps.newHashMap();
            if (!overtimePlan.get("ksrq").equals(overtimePlan.get("jsrq"))){
                map.put("sfkt","1");
            }else {
                map.put("sfkt","0");
            }
            //查找对应的考勤项目
            String querySql = "select id 'key',ksjbbxydk,jsjbbxydk,tqdkyxfzs,thdkyxfzs,jbwdhlfzs,jbzzhlfzs,tqdkjrjb,thdkjrjb,jbscbdccsqsc,zdkcjcxxsc,ccclfs,rzdjbxss,yzdjbxss,zzdjbxss,jbzdzjqye,jbqsfzs,ccqszhdhsfzs,hsl,hsdw from uf_jcl_kq_kqxm where id=?";
            attendanceItems = DbTools.getSqlToList(querySql,overtimePlan.get("jblx"));


            map.put("bcxx",schedulingdateMap.get(0) == null ? "0" :schedulingdateMap.get(0).get("bcxx"));
            map.put("bcsdxx",schedulingdateMap.get(0) == null ? "":schedulingdateMap.get(0).get("bcsdxx"));
            if (resultList.size()>0){
                map.put("edsc",Util.null2String(resultList.get(0).get("edsc")));
                map.put("sfdx",Util.null2String(resultList.get(0).get("sfdx")));
                map.put("zddxfz",Util.null2String(resultList.get(0).get("zddxfz")));
                map.put("dxhs",Util.null2String(resultList.get(0).get("dxhs")));
            }else {
                map.put("edsc","0");
            }
            map.put("bdlx", ClassSegmentTypeEnum.OVERTIME_PLAN.getKey());
            map.put("dtkssj",overtimePlan.get("kssj"));
            map.put("dtjssj",overtimePlan.get("jssj"));
            map.put("ksdk","0");
            map.put("jsdk","0");
            if (schedulingdateMap.size()>0){
                map.put("sfxx",Util.null2String(schedulingdateMap.get(0).get("sfxx")));
            }
            map.put("tqdkfzs","60");
            map.put("thdkfzs","60");
            map.put("rqlx",dateMap.get(e.getKey()));
            map.put("edxss",overtimePlan.get("jbsc"));
            map.put("jblx",attendanceItems);
            if (attendanceItems.size() >0){
                map.put("ksdk",attendanceItems.get(0).get("ksjbbxydk"));
                map.put("jsdk",attendanceItems.get(0).get("jsjbbxydk"));
                map.put("tqdkfzs",attendanceItems.get(0).get("tqdkyxfzs"));
                map.put("thdkfzs",attendanceItems.get(0).get("thdkyxfzs"));
                map.put("jbwdhlfzs",attendanceItems.get(0).get("jbwdhlfzs"));
                map.put("jbzzhlfzs",attendanceItems.get(0).get("jbzzhlfzs"));
            }
            if (resultList.size() > 1){
                String kssjbegin = e.getKey() +" "+resultList.get(0).get("dtkssj");
                String kssjend = e.getKey() +" "+resultList.get(resultList.size()-1).get("dtkssj");
                String kssj = e.getKey() +" "+overtimePlan.get("kssj");
                if (DateUtil.getTime(kssj).compareTo(DateUtil.getTime(kssjbegin)) <0){
                    //加班计划在开头
                    if (resultList.get(0).get("dtkssj").equals(overtimePlan.get("jssj")) &&
                            resultList.get(0).get("ksdk").equals(CheckBoxEnum.CHECKED.getKey()) &&
                            map.get("ksdk").equals(CheckBoxEnum.CHECKED.getKey()) &&
                            map.get("jsdk").equals(CheckBoxEnum.CHECKED.getKey())){
                        //当加班结束时间和早上打卡时间重合时

                    }
                    resultList.add(0,map);
                }else if (DateUtil.getTime(kssj).compareTo(DateUtil.getTime(kssjend)) >0){
                    //加班计划在末尾
                    if (resultList.get(0).get("dtjssj").equals(overtimePlan.get("kssj")) &&
                            resultList.get(0).get("jsdk").equals(CheckBoxEnum.CHECKED.getKey()) &&
                            map.get("ksdk").equals(CheckBoxEnum.CHECKED.getKey()) &&
                            map.get("jsdk").equals(CheckBoxEnum.CHECKED.getKey())){
                        //当加班结束时间和晚上下班时间重合时1

                    }
                    resultList.add(map);
                }else {
                    //加班计划在中间
                    for (int j=1;j<resultList.size();j++){
                        String kssj1 = e.getKey() +" "+resultList.get(j).get("dtkssj");
                        String kssj2 = e.getKey() +" "+overtimePlan.get("kssj");
                        String kssj3 = e.getKey() +" "+resultList.get(j-1).get("dtkssj");
                        if (DateUtil.getTime(kssj1).compareTo(DateUtil.getTime(kssj2)) >=0 &&  DateUtil.getTime(kssj3).compareTo(DateUtil.getTime(kssj2)) <=0){
                            resultList.add(j,map);
                            break;
                        }
                    }
                }
            }else {
                resultList.add(map);
            }

        }

        schedulMap.put("schedulingResultsMap",resultMap);
        log.info("SchedulingResults : [{}]",resultMap);
        return schedulMap;
    }


    /**
     * 获得打卡数据
     * @param params
     * @return
     */
    @Override
    public List<Map<String, Object>> getClockInTime(Map<String, Object> params) {
        Map<String,Object> result = commandExecutor.execute(new GetClockInTimeItemCmd(params));
        List<Map<String, Object>> resultList = (List<Map<String, Object>>)result.get("resultList");
        return resultList;
    }

    @Override
    public void recordItem(Map<String, Object> params) {
        commandExecutor.execute(new RecordDataCmd(params));
    }

    @Override
    public Map<String, Object> getNeedRecordClockInTime(List<Map<String,Map<String,Object>>> clcokInTimeData) {
        Map<String, Object> resultMap = Maps.newHashMap();
        int inIndex = 1;
        int outIndex = 1;
        int jcCloumns = 8;
        for (Map<String,Map<String,Object>> clcokInTimeMap : clcokInTimeData){
            //卡点
            String point = "";
            //当天打卡数据
            Map<String,Object> clcokInTime = null;
            for (Map.Entry<String,Map<String,Object>> entry :clcokInTimeMap.entrySet()){
                point = entry.getKey();
                clcokInTime = entry.getValue();
            }
            //需要计算的班次打卡时间点
            String pointTime = point.split("\\|")[0];
            //start：开始打卡时间点，end：结束打卡时间点
            String pointType = point.split("\\|")[1];
            //empty:漏卡，equal:打卡时间和班次时间相等，before：打卡时间在班次时间之前，after：打卡时间在班次时间之后
            String timeType = point.split("\\|")[2];


            if (ClockPointEnum.START.getKey().equals(pointType)){
                //开始时间打卡
                String key = "j"+inIndex;
                if (!ClockPointEnum.EMPTY.getKey().equals(timeType) && clcokInTime != null){
                    String value = "'"+clcokInTime.get("signtime")+"'";
                    resultMap.put(key,value);
                }else {
                    resultMap.put(key,"NULL");
                }
                inIndex++;
            }else if (ClockPointEnum.END.getKey().equals(pointType)){
                //结束时间打卡
                String key = "c"+outIndex;
                if (!ClockPointEnum.EMPTY.getKey().equals(timeType) && clcokInTime != null){
                    String value = "'"+clcokInTime.get("signtime")+"'";
                    resultMap.put(key,value);
                }else {
                    resultMap.put(key,"NULL");
                }
                outIndex++;
            }

        }
        for (int i=inIndex;i<jcCloumns;i++){
            String key = "j"+i;
            resultMap.put(key,"NULL");
        }
        for (int i=outIndex;i<jcCloumns;i++){
            String key = "c"+i;
            resultMap.put(key,"NULL");
        }
        return resultMap;
    }

    /**
     * 获取打卡卡点
     * @param params
     * @return
     */
    @Override
    public List<Map<String, Map<String, Object>>> getClockInPointCmd(Map<String,Object> params) {
        Map<String,Object> resultMap = commandExecutor.execute(new GetClockInPointCmd(params));

        return (List<Map<String,Map<String,Object>>>)resultMap.get("clcokInTimeData");
    }

    /**
     * 计算出勤时长
     * @param params
     * @return
     */
    @Override
    public double computeAttendanceDuration(Map<String, Object> params) {
        Map<String,Object> resultMap = commandExecutor.execute(new ComputeAttendanceDurationCmd(params));
        return Double.valueOf(resultMap.get("attendanceDuration").toString());
    }
}
