package com.engine.attendance.attendanceanalysis.cmd.workovertime;

import com.engine.attendance.enums.AccountingUnitEnum;
import com.engine.attendance.enums.CheckBoxEnum;
import com.engine.attendance.enums.DateTypeEnum;
import com.engine.attendance.enums.DelayTypeEnum;
import com.engine.common.biz.AbstractCommonCommand;
import com.engine.common.entity.BizLogContext;
import com.engine.common.util.DateUtil;
import com.engine.common.util.DbTools;
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.TimeUtil;
import weaver.general.Util;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 根据相关设置控制加班时长，并入库
 */
@Slf4j
public class SaveWorkOverTimeCmd extends AbstractCommonCommand<Map<String,Object>> {
    public SaveWorkOverTimeCmd(Map<String, Object> params) {
        this.params = params;
    }
    @Override
    public BizLogContext getLogContext() {
        return null;
    }

    @Override
    public Map<String, Object> execute(CommandContext commandContext) {

        //加班项目
        List<Map<String, Object>> workTimeBeLateItems = (List<Map<String,Object>>)params.get("workTimeBeLateItems");
        //加班时长
        double jbsc = Double.valueOf(params.get("jbsc").toString());
        //班次
        Map<String, Object> scheduleMap = (Map<String, Object>)params.get("scheduleMap");

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


        //超出限制时长的处理方式
        String ccclfs = Util.null2String(workTimeBeLateItems.get(0).get("ccclfs"));
        //工作日加班最大小时数
        String rzdjbxss = Util.null2String(workTimeBeLateItems.get(0).get("rzdjbxss"));
        //每周最大加班小时数
        String yzdjbxss = Util.null2String(workTimeBeLateItems.get(0).get("yzdjbxss"));
        //每月最大加班小时数
        String zzdjbxss = Util.null2String(workTimeBeLateItems.get(0).get("zzdjbxss"));
        //加班时长自动转入假期余额
        String jbzdzjqye= Util.null2String(workTimeBeLateItems.get(0).get("jbzdzjqye"));
        //最小加班分钟数
        String jbqsfzs = Util.null2String(workTimeBeLateItems.get(0).get("jbqsfzs"));
        //超出最小时长后的单次累加分钟数
        String ccqszhdhsfzs = Util.null2String(workTimeBeLateItems.get(0).get("ccqszhdhsfzs"));
        //核算量
        double workOverTimeHsl = Double.valueOf(Util.null2String(workTimeBeLateItems.get(0).get("hsl")));
        //核算单位
        String workOverTimeHsdw = Util.null2String(workTimeBeLateItems.get(0).get("hsdw"));
        //分析日期
        String analysisDate = Util.null2String(params.get("analysisDate"));
        //实际开始时间
        String realityStartTime = Util.null2String(params.get("realityStartTime"));
        //实际结束时间
        String realityEndime = Util.null2String(params.get("realityEndime"));
        //考勤项目
        List<Map<String,Object>> attendanceItems = (List<Map<String,Object>>)params.get("attendanceItems");

        long diffdays = Long.valueOf(Util.null2String(params.get("diffdays")));



        String rqlx = Util.null2String(scheduleMap.get("rqlx"));

        List<Map<String, Object>> workOverTimeResults = null;

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

        if (!"".equals(jbqsfzs)){
            if (jbsc < Integer.valueOf(jbqsfzs)){
                //小于最小加班分钟数不算加班
                workOverTimeItems.put("item",workTimeBeLateItems.get(0).get("key"));
                workOverTimeItems.put("itemduration","0");
                return workOverTimeItems;
            }else if (jbsc >= Integer.valueOf(jbqsfzs) && !"".equals(ccqszhdhsfzs)){

                jbsc = Double.valueOf(Utils.getItemdurationDown(Integer.valueOf(ccqszhdhsfzs), AccountingUnitEnum.MINUTES.getKey(),Double.valueOf(jbsc).intValue()-Integer.valueOf(jbqsfzs),AccountingUnitEnum.MINUTES)).intValue()+Integer.valueOf(jbqsfzs);
            }
        }
        if (jbsc <= 0 || "".equals(realityStartTime) || "".equals(realityEndime)){
            //加班时长为0
            workOverTimeItems.put("item",workTimeBeLateItems.get(0).get("key"));
            workOverTimeItems.put("itemduration","0");
            return workOverTimeItems;
        }


        //自动扣除
        if ("2".equals(ccclfs) && workOverTimeResults == null){
            String startDate = analysisDate.split("-")[0]+"-"+ analysisDate.split("-")[1]+"-01";
            String endDate = analysisDate.split("-")[0]+"-"+ analysisDate.split("-")[1]+"-"+diffdays;
            workOverTimeResults =getWorkOverTimeResults(startDate,endDate,userId);

        }
        if ("2".equals(ccclfs) && !"".equals(rzdjbxss) && (DateTypeEnum.WORK_DAY.getKey().equals(rqlx) || DateTypeEnum.CHANGECLASS.getKey().equals(rqlx))){
            //工作日加班最大数
            double maxDayTime = Double.valueOf(rzdjbxss) *60;
            if (jbsc > maxDayTime){
                jbsc = maxDayTime;
            }
        }
        if ("2".equals(ccclfs) && !"".equals(zzdjbxss)){
            //每周最大加班小时数
            double weekTime = getWeekTime(workOverTimeResults,analysisDate);
            double maxWeekTime = Double.valueOf(zzdjbxss) *60;
            double time = jbsc+weekTime;
            if (time > maxWeekTime){
                jbsc = maxWeekTime-weekTime;
            }
        }
        if ("2".equals(ccclfs) && !"".equals(yzdjbxss)){
            //每月最大加班数
            double monthTime = getMonthTime(workOverTimeResults,analysisDate);
            double maxMonthTime = Double.valueOf(yzdjbxss) *60;
            double time = jbsc+monthTime;
            if (time > maxMonthTime){
                jbsc = maxMonthTime-monthTime;
            }
        }
        log.info("最终加班时长: {}",jbsc);
        workOverTimeItems.put("item",workTimeBeLateItems.get(0).get("key"));
        double itemduration = Utils.getItemdurationDown(workOverTimeHsl,workOverTimeHsdw,Long.valueOf(Math.round(jbsc)).intValue(),AccountingUnitEnum.MINUTES);
        workOverTimeItems.put("itemduration",itemduration);

        /**
         * 是否是有出勤结果
         */
        String sql = "select id from uf_jcl_kq_cqjg where ygid=? and rq=?";
        List<Map<String,Object>> dataList = DbTools.getSqlToList(sql,userId,analysisDate);
        String id = dataList.size()>0?Util.null2String(dataList.get(0).get("id")):"";
        /**
         * 入加班结果表
         */
        Map<String,Object> insertParam = Maps.newHashMap();
        insertParam.put("jbry",userId);
        insertParam.put("sjksrq",realityStartTime.split(" ")[0]);
        insertParam.put("sjkssj",realityStartTime.split(" ")[1]);
        insertParam.put("sjjsrq",realityEndime.split(" ")[0]);
        insertParam.put("sjjssj",realityEndime.split(" ")[1]);
        insertParam.put("sjjbsc",itemduration);
        insertParam.put("jbjgly","4");
        insertParam.put("jblx",workTimeBeLateItems.get(0).get("key"));
        insertParam.put("lyid",userId+"-"+ DateUtil.getCurrentDate());
        insertParam.put("zt","1");
        insertParam.put("eddxsc",0);
        insertParam.put("edjxsc",0);
        insertParam.put("ydxsc",0);
        insertParam.put("wdxsc",0);
        /**
         * 入假期余额
         */
        //加班时长自动转入假期余额
        if (CheckBoxEnum.CHECKED.getKey().equals(jbzdzjqye)){
            Map<String,Object> insertHoliDayParam = Maps.newHashMap();
            insertHoliDayParam.put("ygid",userId);
            insertHoliDayParam.put("jqid",workTimeBeLateItems.get(0).get("zrdjb"));
            insertHoliDayParam.put("lyid",userId+"-"+DateUtil.getCurrentDate());
            Map<String,Object> holidayItem = getHolidayItem(workTimeBeLateItems.get(0).get("zrdjb").toString(),attendanceItems);

            double ktsc = Utils.getItemdurationDown(Double.valueOf(holidayItem.get("hsl").toString()),holidayItem.get("hsdw").toString(),Double.valueOf(jbsc).intValue(),AccountingUnitEnum.MINUTES);

            insertHoliDayParam.put("ktsc",ktsc);
            insertHoliDayParam.put("yxsc",0);
            insertHoliDayParam.put("wxsc",ktsc);
            insertHoliDayParam.put("ztsc",0);
            insertHoliDayParam.put("jxsc",0);
            insertHoliDayParam.put("yqsc",0);
            insertHoliDayParam.put("yqyxsc",0);
            insertHoliDayParam.put("zfsc",0);

            insertParam.put("eddxsc",itemduration);
            insertParam.put("wdxsc",itemduration);

            //转入的假期额度生效日期
            String yesxrq = Util.null2String(workTimeBeLateItems.get(0).get("yesxrq"));
            if ("0".equals(yesxrq)){
                //一月后
                insertHoliDayParam.put("sxrq",DateUtil.lastMonth(analysisDate,DateUtil.yyyyMMdd));
            }else if ("1".equals(yesxrq)){
                //次月
                insertHoliDayParam.put("sxrq",DateUtil.lastMonth(analysisDate)+"-01");
            }else if ("2".equals(yesxrq)){
                //次日
                insertHoliDayParam.put("sxrq",DateUtil.AfterDay(analysisDate,1));
            }
            //额度可用的周期
            String yekyzq = Util.null2String(workTimeBeLateItems.get(0).get("yekyzq"));
            if ("0".equals(yekyzq)){
                //一个月
                insertHoliDayParam.put("jzrq",DateUtil.nextMonth(insertHoliDayParam.get("sxrq").toString(),1,DateUtil.yyyyMMdd));
            }else if ("1".equals(yekyzq)){
                //两个月
                insertHoliDayParam.put("jzrq",DateUtil.nextMonth(insertHoliDayParam.get("sxrq").toString(),2,DateUtil.yyyyMMdd));
            }else if ("2".equals(yekyzq)){
                //三个月
                insertHoliDayParam.put("jzrq",DateUtil.nextMonth(insertHoliDayParam.get("sxrq").toString(),3,DateUtil.yyyyMMdd));
            }else if ("3".equals(yekyzq)){
                //六个月
                insertHoliDayParam.put("jzrq",DateUtil.nextMonth(insertHoliDayParam.get("sxrq").toString(),6,DateUtil.yyyyMMdd));
            }else if ("4".equals(yekyzq)){
                //十二个月
                insertHoliDayParam.put("jzrq",DateUtil.nextMonth(insertHoliDayParam.get("sxrq").toString(),12,DateUtil.yyyyMMdd));
            }else if ("5".equals(yekyzq)){
                //当前季度
                insertHoliDayParam.put("jzrq",DateUtil.getCurrentQuarter(insertHoliDayParam.get("sxrq").toString()));
            }else if ("6".equals(yekyzq)){
                //当前半年
                insertHoliDayParam.put("jzrq",DateUtil.getCurrentHalfYear(insertHoliDayParam.get("sxrq").toString()));
            }else if ("7".equals(yekyzq)){
                //当前一年
                insertHoliDayParam.put("jzrq",insertHoliDayParam.get("sxrq").toString().split("-")[0]+"-12-31");
            }

            String zdyqsc = Util.null2String(workTimeBeLateItems.get(0).get("zdyqsc"));
            if (DelayTypeEnum.ONE_MONTH.getKey().equals(zdyqsc)){
                //一个月
                insertHoliDayParam.put("yqsxrq",DateUtil.nextMonth(insertHoliDayParam.get("jzrq").toString(),1,DateUtil.yyyyMMdd));
            }else if (DelayTypeEnum.TWO_MONTH.getKey().equals(zdyqsc)){
                //两个月
                insertHoliDayParam.put("yqsxrq",DateUtil.nextMonth(insertHoliDayParam.get("jzrq").toString(),2,DateUtil.yyyyMMdd));
            }else if (DelayTypeEnum.THREE_MONTH.getKey().equals(zdyqsc)){
                //三个月
                insertHoliDayParam.put("yqsxrq",DateUtil.nextMonth(insertHoliDayParam.get("jzrq").toString(),3,DateUtil.yyyyMMdd));
            }else if (DelayTypeEnum.HALF_YEAR.getKey().equals(zdyqsc)){
                //半年
                insertHoliDayParam.put("yqsxrq",DateUtil.nextMonth(insertHoliDayParam.get("jzrq").toString(),6,DateUtil.yyyyMMdd));
            }else if (DelayTypeEnum.ONE_YEAR.getKey().equals(zdyqsc)){
                //一年
                insertHoliDayParam.put("yqsxrq",DateUtil.nextMonth(insertHoliDayParam.get("jzrq").toString(),12,DateUtil.yyyyMMdd));
            }

            updateholidayResult(id,insertHoliDayParam);
        }
        updateOverTimeResult(id,insertParam);

        return workOverTimeItems;
    }

    public List<Map<String, Object>> getWorkOverTimeResults(String startDate,String endDate,String userId){
        String sql = "select sjjbsc,sjksrq,sjjsrq from uf_jcl_kq_jbjg where jbry=? and sjksrq>? and sjjsrq<?";
        List<Map<String, Object>> dataList = DbTools.getSqlToList(sql,userId,startDate,endDate);
        return dataList;
    }
    /**
     * 获得工作日加班数
     * @param dataList
     * @return
     */
    public int getWorkDayTime(List<Map<String, Object>> dataList,String date){
        List<Map<String, Object>> list = dataList.stream().filter(e->date.equals(e.get("sjksrq"))).collect(Collectors.toList());
        int totalHour = list.stream().mapToInt(e->Integer.valueOf(e.get("sjjbsc").toString())).sum();
        return totalHour;
    }
    /**
     * 获得一周加班数
     * @param dataList
     * @return
     */
    public int getWeekTime(List<Map<String, Object>> dataList,String date){
        int day = TimeUtil.getDayOfWeek(date);
        if (day ==0){
            day = 7;
        }
        String startDate = DateUtil.beforeDay(date,day-1);
        String endDate = DateUtil.AfterDay(date,7-day);
        List<Map<String, Object>> list = dataList.stream().filter(e->{
            String sjksrq = Util.null2String(e.get("sjksrq"));
            if (DateUtil.getTime(sjksrq).compareTo(DateUtil.getTime(startDate)) >=0 &&
                    DateUtil.getTime(sjksrq).compareTo(DateUtil.getTime(endDate)) <=0  &&
                    DateUtil.getTime(sjksrq).compareTo(DateUtil.getTime(date)) !=0){
                return true;
            }else {
                return false;
            }
        }).collect(Collectors.toList());
        int totalHour = list.stream().mapToInt(e->Integer.valueOf(e.get("sjjbsc").toString())).sum();
        return totalHour;
    }
    /**
     * 获得一个月加班数
     * @param dataList
     * @return
     */
    public int getMonthTime(List<Map<String, Object>> dataList,String date){
        List<Map<String, Object>> list = dataList.stream().filter(e->DateUtil.getTime(e.get("sjksrq").toString()).compareTo(DateUtil.getTime(date)) !=0).collect(Collectors.toList());
        int totalHour = list.stream().mapToInt(e->Integer.valueOf(e.get("sjjbsc").toString())).sum();
        return totalHour;
    }

    /**
     * 更新加班结果
     */
    public void updateOverTimeResult(String lyid, Map<String,Object> insertParam){
        if (!"".equals(lyid)){
            String sql = "select edjxsc,ydxsc from uf_jcl_kq_jbjg where lyid=?";
            List<Map<String,Object>> overTimeResultList = DbTools.getSqlToList(sql,lyid);
            if (overTimeResultList.size() > 0){
                Map<String,Object> overTimeResult = overTimeResultList.get(0);
                insertParam.put("edjxsc",overTimeResult.get("edjxsc"));
                insertParam.put("ydxsc",overTimeResult.get("ydxsc"));
                double eddxsc = Utils.convertDouble(insertParam.get("eddxsc"));
                double ydxsc = Utils.convertDouble(overTimeResult.get("ydxsc"));
                insertParam.put("wdxsc",String.format("%.2f",eddxsc-ydxsc));
            }
        }

        Utils.InsertFormTable("uf_jcl_kq_jbjg",insertParam,(Map<String,String>)params.get("formmodeIdMap"));

    }
    /**
     * 更新假期余额
     * 当假期余额为0不记录假期余额，如果当天已有该加班的假期余额记录则更新。
     */
    public void updateholidayResult(String lyid,Map<String,Object> insertParam){
        double ktsc = Utils.convertDouble(insertParam.get("ktsc"));
        if (!"".equals(lyid)) {
            String sql = "select yxsc,ztsc,zfsc,jxsc,yqsc,yqyxsc from uf_jcl_kq_jqye where lyid=?";
            List<Map<String,Object>> holidayList = DbTools.getSqlToList(sql,lyid);
            if (holidayList.size() > 0){
                Map<String,Object> holidayMap = holidayList.get(0);
                insertParam.put("yxsc",holidayMap.get("yxsc"));
                insertParam.put("ztsc",holidayMap.get("ztsc"));
                insertParam.put("zfsc",holidayMap.get("zfsc"));
                insertParam.put("jxsc",holidayMap.get("jxsc"));
                insertParam.put("yqsc",holidayMap.get("yqsc"));
                insertParam.put("yqyxsc",holidayMap.get("yqyxsc"));
                double wxsc = ktsc-Utils.convertDouble(insertParam.get("yxsc"))-Utils.convertDouble(holidayMap.get("ztsc"))-Utils.convertDouble(holidayMap.get("zfsc"));
                insertParam.put("wxsc",String.format("%.2f",wxsc));
            }else {
                if (ktsc == 0){
                    insertParam.put("lyid",lyid);
                }
            }
            Utils.InsertFormTable("uf_jcl_kq_jqye",insertParam,(Map<String,String>)params.get("formmodeIdMap"));
        }else {
            if (ktsc !=0){
                Utils.InsertFormTable("uf_jcl_kq_jqye",insertParam,(Map<String,String>)params.get("formmodeIdMap"));
            }
        }


    }

    public Map<String,Object> getHolidayItem(String holidayId,List<Map<String,Object>> attendanceItems){
        List<Map<String,Object>> holidayList = attendanceItems.stream().filter(e->e.get("key").equals(holidayId)).collect(Collectors.toList());
        if (holidayList.size() > 0){
            return holidayList.get(0);
        }else {
            String sql = "select hsl,hsdw from uf_jcl_kq_kqxm where id=?";
            holidayList = DbTools.getSqlToList(sql,holidayId);
            return holidayList.get(0);
        }
    }

}
