package com.engine.attendance.attendanceanalysis.cmd;

import com.engine.attendance.enums.*;
import com.engine.common.biz.AbstractCommonCommand;
import com.engine.common.entity.BizLogContext;
import com.engine.common.util.DateUtil;
import com.engine.common.util.Utils;
import com.engine.core.interceptor.CommandContext;
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 ComputeAttendanceDurationCmd extends AbstractCommonCommand<Map<String,Object>> {

    public ComputeAttendanceDurationCmd(Map<String,Object> params){
        this.params=params;
    }
    @Override
    public BizLogContext getLogContext() {
        return null;
    }

    @Override
    public Map<String, Object> execute(CommandContext commandContext) {
        Map<String,Object> resultMap = Maps.newHashMap();
        //排班
        List<Map<String, Object>> scheduleResult = (List<Map<String, Object>>)params.get("scheduleResult");
        //请假记录
        List<Map<String,Object>> askForLeaveList = (List<Map<String,Object>>)params.get("askForLeaveList");
        //请假项目
        Map<String,Map<String,Object>> askForLeaveItems = (Map<String,Map<String,Object>>)params.get("askForLeaveItems");
        //外出记录
        List<Map<String,Object>> evectionList = (List<Map<String,Object>>)params.get("evectionList");
        //外出项目
        Map<String,Map<String,Object>> evectionItems = (Map<String,Map<String,Object>>)params.get("evectionItems");
        //请假后消除的异常
        List<Map<String,Object>> offsetAskForLeaveAnomaly = (List<Map<String,Object>>)params.get("offsetAskForLeaveAnomaly");
        //出差外出后消除的异常
        List<Map<String,Object>> offsetEvectionAnomaly = (List<Map<String,Object>>)params.get("offsetEvectionAnomaly");
        //分析日期
        String analysisDate = Util.null2String(params.get("analysisDate"));

        //经过请假外出处理过的异常项目
        List<Map<String,Object>> abnormalClockInList = (List<Map<String,Object>>)params.get("abnormalClockInList");
        //单位小时
        double edsc = Double.valueOf(scheduleResult.get(0).get("edsc").toString());
        if (0 == edsc){
            resultMap.put("attendanceDuration",edsc);
            return resultMap;
        }
        //单位分钟
        /**
         * 当工作时间段存在异常项目时
         */
        abnormalClockInList = abnormalClockInList.stream().filter(e->e.get("bdlx").equals(ClassSegmentTypeEnum.WORK_TIME.getKey())).collect(Collectors.toList());
        double abnormalTime = 0;
        for (Map<String,Object> abnormalClockInMap : abnormalClockInList){
            String hsdw = Util.null2String(abnormalClockInMap.get("hsdw"));
            double itemduration = Double.valueOf(Util.null2String(abnormalClockInMap.get("itemduration")));
            AttendanceItemTypeEnum itemType =  (AttendanceItemTypeEnum)abnormalClockInMap.get("itemType");
            String kczgsc = Util.null2String(abnormalClockInMap.get("kczgsc"));
            if (itemType == AttendanceItemTypeEnum.MISSE_CARD){
                //早上漏卡
                abnormalTime = abnormalTime + edsc*60;
            }
            if (!CheckBoxEnum.CHECKED.getKey().equals(kczgsc)){
                continue;
            }
            if (AccountingUnitEnum.DAY.getKey().equals(hsdw)){
                abnormalTime = abnormalTime + edsc*Double.valueOf(itemduration)*60;
            }else if (AccountingUnitEnum.HOUR.getKey().equals(hsdw)){
                abnormalTime = abnormalTime+Double.valueOf(itemduration)*60;
            }else if (AccountingUnitEnum.MINUTES.getKey().equals(hsdw)){
                abnormalTime = abnormalTime+Double.valueOf(itemduration);
            }

        }
        /**
         * 当存在请假时，考虑扣除请假时长
         */
        double askForLeaveTime = removeAskForLeave(analysisDate,scheduleResult,askForLeaveList,askForLeaveItems,offsetAskForLeaveAnomaly);

        /**
         * 当存在外出时，考虑扣除外出时长
         */
        double evectionTimeTime = removeEvection(analysisDate,scheduleResult,evectionList,evectionItems,offsetEvectionAnomaly);

        log.info("abnormalTime : {},askForLeaveTime : {},evectionTimeTime:{}",abnormalTime,askForLeaveTime,evectionTimeTime);
        double deductTime = Double.valueOf(String.format ("%.2f",(abnormalTime+askForLeaveTime+evectionTimeTime)/60));
        edsc = edsc-deductTime;
        if (edsc < 0){
            edsc=0;
        }

        resultMap.put("attendanceDuration",String.format ("%.2f", edsc));
        return resultMap;
    }

    public double removeAskForLeave(String analysisDate,List<Map<String, Object>> scheduleResult,List<Map<String,Object>> askForLeaveList,
                                    Map<String,Map<String,Object>> askForLeaveItems,List<Map<String, Object>> offsetAskForLeaveAnomaly){
        double employTime = 0;
        double edsc = Double.valueOf(scheduleResult.get(0).get("edsc").toString());

        log.info("removeAskForLeave scheduleResult:{},askForLeaveList:{},askForLeaveItems:{},offsetAskForLeaveAnomaly:{}",scheduleResult,
                askForLeaveList,askForLeaveItems,offsetAskForLeaveAnomaly);
        for (int i=0;i<askForLeaveList.size();i++){
            //请假时长
            String qjsc = Util.null2String(askForLeaveList.get(i).get("qjsc"));
            //请假项目
            Map<String,Object> askForLeaveItem = askForLeaveItems.get(askForLeaveList.get(i).get("jqlx"));
            //半天请假
            String btj = Util.null2String(askForLeaveList.get(i).get("btj"));
            //作用时段
            String zysd = Util.null2String(askForLeaveItem.get("zysd"));
            if (!zysd.contains(WorkForTimeEnum.WORK_TIME.getKey()) && !WorkForTimeEnum.ALL_TIME.getKey().equals(zysd)){
                continue;
            }

            if ("".equals(Util.null2String(askForLeaveList.get(i).get("kssj"))) || "".equals(Util.null2String(askForLeaveList.get(i).get("jssj")))){
                //弹性请假,半天出差
                if (CheckBoxEnum.CHECKED.getKey().equals(btj)){
                    //半天出差
                    employTime = employTime + edsc*30;
                }else if (!"".equals(qjsc)){
                    //时长请假
                    if (offsetAskForLeaveAnomaly.size() > 0){
                        List<Map<String, Object>> list = offsetAskForLeaveAnomaly.stream().filter(e->ClassSegmentTypeEnum.WORK_TIME.getKey().equals(e.get("bdlx"))).collect(Collectors.toList());
                        employTime += Math.round(list.size()/Double.valueOf(offsetAskForLeaveAnomaly.size()) *Double.valueOf(qjsc)*60);
                    }else {
                        employTime +=Double.valueOf(qjsc)*60;
                    }
                }
            }else {
                //按照开始时间，结束时间请假
                for (Map<String, Object> scheduleMap:scheduleResult){
                    if (ClassSegmentTypeEnum.WORK_TIME.getKey().equals(scheduleMap.get("bdlx"))){
                        String dtkssj = Utils.getkssjTime(scheduleMap,analysisDate);
                        String dtjssj = Utils.getjssjTime(scheduleMap,analysisDate);

                        employTime +=Utils.getStartAndEndTime(dtkssj,dtjssj,askForLeaveList.get(i));
                    }
                }

            }
        }
        return employTime;
    }

    public double removeEvection(String analysisDate,List<Map<String, Object>> scheduleResult,List<Map<String,Object>> evectionList,
                                    Map<String,Map<String,Object>> evectionItems,List<Map<String, Object>> offsetEvectionAnomaly){
        double employTime = 0;
        double edsc = Double.valueOf(scheduleResult.get(0).get("edsc").toString());
        for (int i=0;i<evectionList.size();i++){
            //请假时长
            String ccsc = Util.null2String(evectionList.get(i).get("ccsc"));
            //请假项目
            Map<String,Object> askForLeaveItem = evectionItems.get(evectionList.get(i).get("cclx"));
            //半天请假
            String btcc = Util.null2String(evectionList.get(i).get("btcc"));
            //作用时段
            String zysd = Util.null2String(askForLeaveItem.get("zysd"));
            if (!zysd.contains(WorkForTimeEnum.WORK_TIME.getKey()) && !WorkForTimeEnum.ALL_TIME.getKey().equals(zysd)){
                continue;
            }

            if ("".equals(Util.null2String(evectionList.get(i).get("kssj"))) || "".equals(Util.null2String(evectionList.get(i).get("jssj")))){
                //弹性请假,半天出差
                if (CheckBoxEnum.CHECKED.getKey().equals(btcc)){
                    //半天出差
                    employTime = employTime + edsc*30;
                }else if (!"".equals(ccsc)){
                    //时长请假
                    if (offsetEvectionAnomaly.size() > 0){
                        List<Map<String, Object>> list = offsetEvectionAnomaly.stream().filter(e->ClassSegmentTypeEnum.WORK_TIME.getKey().equals(e.get("bdlx"))).collect(Collectors.toList());
                        employTime += Math.round(list.size()/Double.valueOf(offsetEvectionAnomaly.size()) *Double.valueOf(ccsc)*60);
                    }else {
                        employTime += Double.valueOf(ccsc)*60;
                    }
                }
            }else {
                //按照开始时间，结束时间请假
                for (Map<String, Object> scheduleMap:scheduleResult){
                    String dtkssj = Utils.getkssjTime(scheduleMap,analysisDate);
                    String dtjssj = Utils.getjssjTime(scheduleMap,analysisDate);
                    if (ClassSegmentTypeEnum.WORK_TIME.getKey().equals(scheduleMap.get("bdlx"))){
                        employTime +=Utils.getStartAndEndTime(dtkssj,dtjssj,evectionList.get(i));
                    }
                }

            }
        }
        return employTime;
    }
}
