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

import com.engine.attendance.attendanceanalysis.cmd.workovertime.GetOvertimeDurationCmd;
import com.engine.attendance.attendanceanalysis.cmd.item.WorkOvertimeItemCmd;
import com.engine.attendance.attendanceanalysis.cmd.workovertime.SaveWorkOverTimeCmd;
import com.engine.attendance.attendanceanalysis.dto.ClockPointDTO;
import com.engine.attendance.attendanceanalysis.service.WorkOverTimeService;
import com.engine.attendance.enums.*;
import com.engine.common.util.DateUtil;
import com.engine.common.util.DbTools;
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.TimeUtil;
import weaver.general.Util;

import java.time.ZoneOffset;
import java.util.Calendar;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
public class WorkOverTimeServiceImpl extends Service implements WorkOverTimeService {
    @Override
    public List<Map<String, Object>> recordWorkOverTime(Map<String, Object> params) {
        //考勤项目
        List<Map<String,Object>> attendanceItems = (List<Map<String,Object>>)params.get("attendanceItems");
        //排班
        List<Map<String, Object>> scheduleResult = (List<Map<String,Object>>)params.get("scheduleResult");
        //分析日期
        String analysisDate = Util.null2String(params.get("analysisDate"));
        //打卡卡点
        List<ClockPointDTO> clcokInTimeDataList = (List<ClockPointDTO>)params.get("clcokInTimeData");

        Map<String,Map<String,Object>> clcokInTimeMap = Maps.newHashMap();

        Calendar calendar = Calendar.getInstance();
        calendar.set(Integer.valueOf(analysisDate.split("-")[0]), Integer.valueOf(analysisDate.split("-")[1]) - 1, 1);

        long diffdays  = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
        params.put("diffdays",diffdays);

        for (ClockPointDTO clockPointDTO :clcokInTimeDataList){
            //当天打卡数据
            Map<String,Object> clcokInTime = clockPointDTO.getClockTime();
            //需要计算的班次打卡时间点
            String pointTime = clockPointDTO.getClassTime();
            clcokInTimeMap.put(pointTime,clcokInTime);
        }
        params.put("clcokInTimeMap",clcokInTimeMap);

        List<Map<String, Object>> restOverTimeList = scheduleResult.stream().filter(e->e.get("bdlx").equals(ClassSegmentTypeEnum.OVERTIME_PLAN.getKey())
                            && ClassSegmentTypeEnum.WORK_TIME.getKey().equals(e.get("beforeClassSegment"))).collect(Collectors.toList());


        /**
         *  非休息班次，加班项目结果集
         */
        List<Map<String, Object>> resultLists = Lists.newArrayList();
        for (Map<String, Object> scheduleMap :scheduleResult){
            List<Map<String,Object>> workTimeBeLateItems = getWorkTimeBeLateItems(scheduleMap,attendanceItems);
            if (workTimeBeLateItems.size() == 0 || ClassSegmentTypeEnum.WORK_TIME.getKey().equals(scheduleMap.get("beforeClassSegment"))){
                continue;
            }

            params.put("workTimeBeLateItems",workTimeBeLateItems);
            params.put("scheduleMap",scheduleMap);
            //获得加班时长以及加班开始时间和结束时间
            Map<String,Object> overTimeDuraionMap = commandExecutor.execute(new GetOvertimeDurationCmd(params));
            params.putAll(overTimeDuraionMap);
            //获得加班项目
            Map<String,Object> itemMap = commandExecutor.execute(new SaveWorkOverTimeCmd(params));
            resultLists.add(itemMap);
        }

        /**
         * 休息班次，工作时段转加班计划项目结果集
         */
        List<Map<String,Object>> restOverTimeDuraion = Lists.newArrayList();
        double jbsc = 0;
        for (Map<String, Object> restOverTimeMap :restOverTimeList){
            List<Map<String,Object>> workTimeBeLateItems = getWorkTimeBeLateItems(restOverTimeMap,attendanceItems);
            if (workTimeBeLateItems.size() == 0){
                continue;
            }
            params.put("workTimeBeLateItems",workTimeBeLateItems);
            params.put("scheduleMap",restOverTimeMap);
            //获得加班时长以及加班开始时间和结束时间
            Map<String,Object> overTimeDuraionMap = commandExecutor.execute(new GetOvertimeDurationCmd(params));
            jbsc += Double.valueOf(overTimeDuraionMap.get("jbsc").toString());
            if (overTimeDuraionMap.get("realityStartTime") != null && overTimeDuraionMap.get("realityEndime") != null){
                restOverTimeDuraion.add(overTimeDuraionMap);
            }
        }
        if (restOverTimeDuraion.size() > 0){
            params.put("jbsc",jbsc);
            String realityStartTime = restOverTimeDuraion.stream().min(Comparator.comparing(e->DateUtil.getTime(e.get("realityStartTime").toString()).toInstant(ZoneOffset.of("+8")).toEpochMilli())).get().get("realityStartTime").toString();
            String realityEndime = restOverTimeDuraion.stream().max(Comparator.comparing(e->DateUtil.getTime(e.get("realityEndime").toString()).toInstant(ZoneOffset.of("+8")).toEpochMilli())).get().get("realityEndime").toString();
            params.put("realityStartTime",realityStartTime);
            params.put("realityEndime",realityEndime);
            Map<String,Object> itemMap = commandExecutor.execute(new SaveWorkOverTimeCmd(params));
            resultLists.add(itemMap);
        }


        return resultLists;
    }

    public List<Map<String,Object>> getWorkTimeBeLateItems(Map<String, Object> scheduleMap,List<Map<String,Object>> attendanceItems){
        String bdlx = Util.null2String(scheduleMap.get("bdlx"));
        Map<String,Object> getWorkOverTimeParam = Maps.newHashMap();

        getWorkOverTimeParam.put("attendanceItems",attendanceItems);
        getWorkOverTimeParam.put("rqlx",scheduleMap.get("rqlx"));
        getWorkOverTimeParam.put("workfor",Utils.getWorkFor(bdlx));
        List<Map<String,Object>> workTimeBeLateItems = Lists.newArrayList();
        if (Utils.ifOverTimeClassSegment(bdlx)){
            if (ClassSegmentTypeEnum.OVERTIME_PLAN.getKey().equals(bdlx)){
                getWorkOverTimeParam.put("workfor",WorkForTimeEnum.PLAN_WORK_OVERTIME.getKey());
                workTimeBeLateItems = (List<Map<String,Object>>)scheduleMap.get("jblx");
            }else {
                Map<String,Object> result = commandExecutor.execute(new WorkOvertimeItemCmd(getWorkOverTimeParam));
                //加班项目
                workTimeBeLateItems = (List<Map<String,Object>>)result.get("attendanceItems");
            }
        }
        return workTimeBeLateItems;
    }

}
