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

import com.engine.jucailinkq.attendance.enums.CheckBoxEnum;
import com.engine.common.biz.AbstractCommonCommand;
import com.engine.common.entity.BizLogContext;
import com.engine.jucailinkq.attendance.vacation.util.VocationCommonUtil;
import com.engine.jucailinkq.common.util.CommonUtil;
import com.engine.jucailinkq.common.util.DateUtil;
import com.engine.jucailinkq.common.util.DbTools;
import com.engine.core.interceptor.CommandContext;
import com.engine.jucailinkq.common.util.Utils;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import weaver.conn.RecordSet;
import weaver.conn.RecordSetTrans;
import weaver.general.Util;

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * 出勤结果数据入库
 */
@Slf4j
public class RecordDataCmd extends AbstractCommonCommand<Map<String,Object>> {

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

    @Override
    public Map<String, Object> execute(CommandContext commandContext) {
        //
        String userId = Util.null2String(params.get("userId"));
        //分析日期
        String analysisDate = Util.null2String(params.get("analysisDate"));
        //项目数据集合
        List<Map<String, Object>> recordDataList = (List<Map<String, Object>>)params.get("recordData");
        //日期类型
        String rqlx = Util.null2String(params.get("rqlx")).equals("")?null:Util.null2String(params.get("rqlx"));
        //班次
        List<Map<String,Object>> classInfo = (List<Map<String,Object>>)params.get("classInfo");
        //进出时间
        Map<String,Object> recordDataTime = (Map<String,Object>)params.get("recordDataTime");
        //出勤时间
        String attendanceDuration = Util.null2String(params.get("attendanceDuration"));
        //加班转假期余额集合
        List<Map<String, Object>> overTimeHolidayList = params.get("overTimeHolidayList")==null?Lists.newArrayList():(List<Map<String, Object>>)params.get("overTimeHolidayList");
        //加班结果集合
        List<Map<String, Object>> overTimeResultList = params.get("overTimeResultList")==null?Lists.newArrayList():(List<Map<String, Object>>)params.get("overTimeResultList");

        Map<String,String> formmodeIdMap = (Map<String,String>)params.get("formmodeIdMap");

        String formmodeid = formmodeIdMap.get("uf_jcl_kq_cqjg");
        //出勤状态
        String cqzt = Util.null2String(params.get("cqzt"));
        //是否休息
        String sfxx = Util.null2String(params.get("sfxx"));

        if ("".equals(sfxx)){
            sfxx= CheckBoxEnum.UNCHECKED.getKey();
        }

        String sql = "select ygid,rq from uf_jcl_kq_cqjg where ygid=? and rq=?";
        List<Map<String,Object>> dataList = DbTools.getSqlToList(sql,userId,analysisDate);
        if (recordDataList.size()>8){
            recordDataList = recordDataList.subList(0,8);
        }
        if (dataList.size() >0){
            sql = "update uf_jcl_kq_cqjg set cqsc="+attendanceDuration+",cqzt="+cqzt+",fxrq='"+DateUtil.getCurrentTime()+"',rqlx="+rqlx+",sfxx="+sfxx;
            if (classInfo.size() == 0 || classInfo.get(0).get("bcxx") == null || "".equals(classInfo.get(0).get("bcxx"))){
                sql = sql + ",bc=NULL,bcbdxx=NULL,";
            }else {
                sql = sql + ",bc="+classInfo.get(0).get("bcxx")+",bcbdxx='"+classInfo.get(0).get("bcsdxx")+"',";
            }
            for (int i =0;i<recordDataList.size();i++){
                String item = Util.null2String(recordDataList.get(i).get("item"));
                String itemduration = Util.null2String(recordDataList.get(i).get("itemduration"));
                int index = i+1;
                sql = sql + "xm"+index+"="+item+",";
                if (!"".equals(itemduration)){
                    sql = sql + "sc"+index+"="+itemduration+",";
                }
            }
            for (int i=recordDataList.size()+1;i<9;i++){
                sql = sql +"xm"+i+"=NULL,sc"+i+"=NULL,";
            }
            if (recordDataTime != null && recordDataTime.size() >0){
                for (Map.Entry<String,Object> entry : recordDataTime.entrySet()){
                    if (entry.getValue() == null || "NULL".equals(entry.getValue()) || "null".equals(entry.getValue())
                    ||"".equals(entry.getValue())){
                        sql = sql + entry.getKey()+"="+entry.getValue()+",";
                    }else {
                        sql = sql + entry.getKey()+"='"+entry.getValue()+"',";
                    }
                }
            }else {
                for (int i=1;i<9;i++){
                    sql = sql + "j"+i+"=NULL,c"+i+"=NULL,";
                }
            }

            sql = sql.substring(0,sql.length()-1) +" where ygid=? and rq=?";
            log.info("update sql : {}",sql);
            DbTools.update(sql,userId,analysisDate);
        }else {
            sql = "select subcompanyid1,departmentid,jobtitle from hrmresource  where id=?";
            List<Map<String,Object>> userList = DbTools.getSqlToList(sql,userId);
            sql = "insert into uf_jcl_kq_cqjg (szjg,ygid,fbid,bm,zw,rq,bc,bcbdxx,cqzt,cqsc,sjzt,fxrq,formmodeid,modeuuid,modedatacreater,modedatacreatertype,modedatacreatedate,modedatacreatetime,rqlx,sfxx,";
            String cloumns = "";
            String value = "?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,";
            List<Object> insertDatas = Lists.newArrayList();
            insertDatas.add(userList.get(0).get("subcompanyid1"));
            insertDatas.add(userId);
            insertDatas.add(userList.get(0).get("subcompanyid1"));
            insertDatas.add(userList.get(0).get("departmentid"));
            insertDatas.add("".equals(userList.get(0).get("jobtitle"))?null:userList.get(0).get("jobtitle"));
            insertDatas.add(analysisDate);
            insertDatas.add(classInfo.size()>0?classInfo.get(0).get("bcxx"):null);
            insertDatas.add(classInfo.size()>0?classInfo.get(0).get("bcsdxx"):null);
            insertDatas.add(cqzt);
            insertDatas.add(attendanceDuration);
            insertDatas.add(1);
            insertDatas.add(DateUtil.getCurrentTime());
            insertDatas.add(formmodeid);
            insertDatas.add(UUID.randomUUID().toString());
            insertDatas.add(1);
            insertDatas.add(0);
            insertDatas.add(DateUtil.getCurrentDate());
            insertDatas.add(DateUtil.getCurrentTime().split(" ")[1]);
            insertDatas.add(rqlx);
            insertDatas.add(sfxx);
            for (int i =0;i<recordDataList.size();i++){
                int index = i+1;
                String item = Util.null2String(recordDataList.get(i).get("item"));
                String itemduration = Util.null2String(recordDataList.get(i).get("itemduration"));

                cloumns = cloumns+"xm"+index+",";
                value = value +"?,";
                insertDatas.add(item);
                if (!"".equals(itemduration)){
                    cloumns = cloumns + "sc"+index+",";
                    value = value +"?,";
                    insertDatas.add(itemduration);
                }
            }
            if (recordDataTime != null && recordDataTime.size() >0){
                for (Map.Entry<String,Object> entry : recordDataTime.entrySet()){
                    if (!"NULL".equals(entry.getValue())){
                        cloumns = cloumns + entry.getKey()+",";
                        value = value + "?,";
                        insertDatas.add(entry.getValue());
                    }
                }
            }
            if (!"".equals(cloumns)){
                cloumns = cloumns.substring(0,cloumns.length()-1);
            }else {
                sql = sql.substring(0,sql.length()-1);
            }
            value = value.substring(0,value.length()-1);
            sql  = sql +cloumns +") values ("+value+")";
            log.info("insert sql : {}",sql);
            log.info("insert data : {}",insertDatas);
            DbTools.update(sql,insertDatas.toArray());

        }

        updateWorkOverTimeDate(userId,analysisDate,overTimeHolidayList,overTimeResultList);
        return null;
    }

    /**
     * 处理加班结果以及加班转假期记录
     * @param userId
     * @param date
     * @param overTimeHolidayList
     * @param overTimeResultList
     */
    public void updateWorkOverTimeDate(String userId,String date,List<Map<String,Object>> overTimeHolidayList,List<Map<String,Object>> overTimeResultList){
        String sql = "select id from uf_jcl_kq_cqjg where ygid=? and rq=?";
        List<Map<String,Object>> dataList = DbTools.getSqlToList(sql,userId,date);
        if (dataList.size() > 0){
            String id = Util.null2String(dataList.get(0).get("id"));

            //处理加班结果
            sql = "select id,jblx,lyid from uf_jcl_kq_jbjg where lyid=? and jbjgly=4";
            List<Map<String,Object>> oldOverTimeList = DbTools.getSqlToList(sql,id);
            for (Map<String,Object> overTimeResult : overTimeResultList){
                overTimeResult.put("lyid",id);
            }
            try {

                updateOverTimeResult(oldOverTimeList,overTimeResultList);

                //处理假期余额
                sql = "select id,jqid,ktsc,yxsc,wxsc,ztsc,zfsc,jxsc,dzkxsc,lyid,lyjblx from uf_jcl_kq_jqye where lyid=? and lylx=4";
                List<Map<String,Object>> oldOverTimeHolidayList = DbTools.getSqlToList(sql,id);
                for (Map<String,Object> overTimeHoliday : overTimeHolidayList){
                    overTimeHoliday.put("lyid",id);
                }
                updateOverTimeHoliday(oldOverTimeHolidayList,overTimeHolidayList);

            }catch (Exception e){
                log.error("updateWorkOverTimeDate error : [{}]",e);
            }
        }
    }

    /**
     * 处理加班结果
     * @param oldResultData
     * @param newResultData
     */
    public void updateOverTimeResult(List<Map<String,Object>> oldResultData,List<Map<String,Object>> newResultData)throws Exception{
        Map<String,Object> operate = Maps.newHashMap();
        operate.put("delete",Lists.newArrayList());
        operate.put("insert",Lists.newArrayList());
        operate.put("update",Lists.newArrayList());
        Map<String,List<Map<String,Object>>> oldOverTimeGroupByType = oldResultData.stream().collect(Collectors.groupingBy(e->Util.null2String(e.get("jblx"))));
        Map<String,List<Map<String,Object>>> overTimeGroupByType = newResultData.stream().collect(Collectors.groupingBy(e->Util.null2String(e.get("jblx"))));

        oldOverTimeGroupByType.entrySet().forEach(e->{
            String jblx = e.getKey();
            List<Map<String,Object>> oldData = e.getValue();
            List<Map<String,Object>> newData = overTimeGroupByType.get(jblx);
            if (newData == null || newData.size() == 0){
                //新数据不存在，老数据存在。老数据需要删除
                List<String> deleteList = (List<String>)operate.get("delete");
                deleteList.addAll(oldData.stream().map(f->f.get("id").toString()).collect(Collectors.toList()));
            }else if (newData.size() == oldData.size()){
                //新数据和老数据条数相等。更新老数据。
                List<Map<String,Object>> updateList = (List<Map<String,Object>>)operate.get("update");
                for (int i =0;i<newData.size();i++){
                    newData.get(i).put("id",oldData.get(i).get("id"));
                }
                updateList.addAll(newData);
            }else {
                //老数据与新数据条数不一致，删除老数据。新增新数据
                List<Map<String,Object>> insertList = (List<Map<String,Object>>)operate.get("insert");
                List<String> deleteList = (List<String>)operate.get("delete");
                deleteList.addAll(oldData.stream().map(f->f.get("id").toString()).collect(Collectors.toList()));
                insertList.addAll(newData);
            }
        });
        overTimeGroupByType.entrySet().forEach(e->{
            String jblx = e.getKey();
            List<Map<String,Object>> newData = e.getValue();
            List<Map<String,Object>> oldData = oldOverTimeGroupByType.get(jblx);
            if (oldData == null || oldData.size() == 0){
                //老数据不存在，新数据存在。新增数据
                List<Map<String,Object>> insertList = (List<Map<String,Object>>)operate.get("insert");
                insertList.addAll(newData);
            }
        });

        List<String> deleteList = (List<String>) operate.get("delete");
        List<Map<String, Object>> updateList = (List<Map<String, Object>>) operate.get("update");
        List<Map<String, Object>> insertList = (List<Map<String, Object>>) operate.get("insert");
        if (deleteList.size() > 0) {
            String deleteSql = "delete from uf_jcl_kq_jbjg where id in (" + String.join(",", deleteList) + ")";
            DbTools.update(deleteSql);
        }
        if (updateList.size() > 0) {
            for (Map<String, Object> updateParam : updateList) {
                Map<String, Object> condition = Maps.newHashMap();
                condition.put("id", updateParam.get("id"));
                DbTools.update(CommonUtil.makeUpdateSql("uf_jcl_kq_jbjg", updateParam, condition));
            }
        }
        if (insertList.size() > 0) {
            for (Map<String, Object> insertParam : insertList) {
                Utils.InsertFormTable("uf_jcl_kq_jbjg",insertParam,(Map<String,String>)params.get("formmodeIdMap"));
            }
        }
    }

    /**
     * 处理加班转调休、假期
     * @param oldHolidayData
     * @param newHolidayData
     */
    public void updateOverTimeHoliday(List<Map<String,Object>> oldHolidayData,List<Map<String,Object>> newHolidayData)throws Exception {
        Map<String,List<Map<String,Object>>> oldHolidayGroupByType = oldHolidayData.stream().collect(Collectors.groupingBy(e->e.get("lyjblx").toString()));
        Map<String,List<Map<String,Object>>> newHolidayGroupByType = newHolidayData.stream().collect(Collectors.groupingBy(e->Util.null2String(e.get("lyjblx"))));

        List<String> deleteList = Lists.newArrayList();
        List<Map<String,Object>> updateList = Lists.newArrayList();
        List<Map<String,Object>> insertList = Lists.newArrayList();
        List<String> revokeHoliday = Lists.newArrayList();
        Map<String,List<Map<String,Object>>> beforeHolidays = Maps.newHashMap();
        for (Map.Entry<String,List<Map<String,Object>>> entry : oldHolidayGroupByType.entrySet()){
            String jblx = entry.getKey();
            Map<String,Object> oldData = entry.getValue().get(0);
            List<Map<String,Object>> newDataList = newHolidayGroupByType.get(jblx);
            double oldktsc = Double.valueOf(oldData.get("ktsc").toString());
            double oldyxsc = Double.valueOf(oldData.get("yxsc").toString());
            double oldwxsc = Double.valueOf(oldData.get("wxsc").toString());
            double oldzfsc = Double.valueOf(oldData.get("zfsc").toString());
            double oldztsc = Double.valueOf(oldData.get("ztsc").toString());
            if (newDataList == null || newDataList.size() == 0 || newDataList.get(0).size() <= 1){
                //新数据不存在或者可休时长为0，老数据存在。
                //删除老数据
                deleteList.add(oldData.get("id").toString());
                if (oldyxsc > 0){
                    //手动撤销所有请假余额
                    revokeHoliday.add(oldData.get("id").toString());
                }
            }else{
                double totalKtsc = newDataList.stream().mapToDouble(e->Double.valueOf(e.get("ktsc").toString())).sum();
                if (totalKtsc == 0){
                    //可休时长为0
                    deleteList.add(oldData.get("id").toString());
                    if (oldyxsc > 0){
                        //手动撤销所有请假余额
                        revokeHoliday.add(oldData.get("id").toString());
                    }
                }else {
                    Map<String,Object> newData = newDataList.get(0);
                    newData.put("ktsc",String.format ("%.2f",totalKtsc));
                    //更新老数据。
                    newData.put("zfsc",oldzfsc);
                    newData.put("ztsc",oldztsc);
                    newData.put("wxsc",VocationCommonUtil.substract(String.format ("%.2f",totalKtsc),oldzfsc,oldztsc,oldyxsc));
                    newData.put("yxsc",oldyxsc);
                    newData.put("id",oldData.get("id"));
                    if (!newData.get("jqid").equals(oldData.get("jqid"))){
                        //假期类型替换
                        revokeHoliday.add(oldData.get("id").toString());
                        newData.put("yxsc",0);
                        newData.put("wxsc",totalKtsc);
                    }else {
                        if (oldwxsc >= 0 && Double.compare(totalKtsc,oldyxsc) <0){
                            //当没有透支时，新的可休时长小于老的已休时长，手动撤销所有已休请假余额。
                            revokeHoliday.add(oldData.get("id").toString());
                            newData.put("yxsc",0);
                            newData.put("wxsc",totalKtsc);
                        }else if (oldwxsc < 0 && Double.compare(totalKtsc,oldktsc) < 0){
                            //当透支时，新的可休时长小于老的可休时长，不撤销继续减
                            double subctractKtsc = new BigDecimal(String.valueOf(totalKtsc)).subtract(new BigDecimal(String.valueOf(oldktsc)),new MathContext(4, RoundingMode.HALF_UP)).doubleValue();
                            newData.put("yxsc",oldyxsc+subctractKtsc);
                            newData.put("wxsc",new BigDecimal(oldData.get("wxsc").toString()).subtract(new BigDecimal(String.valueOf(subctractKtsc)),new MathContext(4, RoundingMode.HALF_UP)).doubleValue());
                        }
                    }
                    updateList.add(newData);
                }
            }
        }
        String queryHolidaySql = "select id,yxsc,wxsc,ktsc,jqid,ztsc,zfsc from uf_jcl_kq_jqye where  ygid=? and jqid=? order by modedatacreatedate desc,modedatacreatetime desc";
        for (Map.Entry<String,List<Map<String,Object>>> entry : newHolidayGroupByType.entrySet()){
            String jblx = entry.getKey();
            List<Map<String,Object>> newDataList = entry.getValue();
            if (newDataList != null && newDataList.size() > 0 && newDataList.get(0).size() > 1){
                double totalKtsc = newDataList.stream().mapToDouble(e->Double.valueOf(e.get("ktsc").toString())).sum();
                Map<String,Object> newData = newDataList.get(0);

                List<Map<String,Object>> oldData = oldHolidayGroupByType.get(jblx);
                if (oldData == null || oldData.size() == 0){
                    newData.put("ktsc",totalKtsc);
                    beforeHolidays.put(newData.get("jqid").toString(),DbTools.getSqlToList(queryHolidaySql,newData.get("ygid"),newData.get("jqid")));
                    //老数据不存在，新数据存在。新增数据
                    insertList.add(newData);
                }
            }
        }


        if (deleteList.size() > 0){
            String deleteSql = "delete from uf_jcl_kq_jqye where id in ("+String.join(",",deleteList)+")";
            DbTools.update(deleteSql);
        }
        if (updateList.size() > 0){
            for (Map<String,Object> updateParam:updateList){
                Map<String,Object> condition = Maps.newHashMap();
                condition.put("id",updateParam.get("id"));
                DbTools.update(CommonUtil.makeUpdateSql("uf_jcl_kq_jqye",updateParam,condition));
            }
        }
        if (insertList.size() > 0){
            for (Map<String,Object> insertParam:insertList){

                List<Map<String,Object>> beforeHolidayList = beforeHolidays.get(insertParam.get("jqid").toString());
                double beforewxsc = 0;
                if (beforeHolidayList != null && beforeHolidayList.size() >0){
                    //假期余额透支功能
                    beforewxsc =Double.valueOf(beforeHolidayList.get(0).get("wxsc").toString());
                }
                if (beforewxsc < 0){
                    insertParam.put("wxsc",Double.valueOf(insertParam.get("ktsc").toString())+beforewxsc);
                    insertParam.put("yxsc",0-beforewxsc);
                }
                boolean excuteResult = Utils.InsertFormTable("uf_jcl_kq_jqye",insertParam,(Map<String,String>)params.get("formmodeIdMap"));
                List<Map<String,Object>> nowdataList = DbTools.getSqlToList(queryHolidaySql,insertParam.get("ygid"),insertParam.get("jqid"));
                if (excuteResult && beforewxsc <0){
                    VocationCommonUtil.handleOverdraftHoliday(beforeHolidayList.get(0),beforewxsc,nowdataList.get(0));
                }
            }
        }
        if (revokeHoliday.size() > 0){
            String sql = "select b.id from uf_jcl_kq_qjjl_dt2 a left join uf_jcl_kq_qjjl_dt1 b on a.glmxid=b.glmxid where a.jqye in ("+String.join(",",revokeHoliday)+")";
            List<String> needRevokeHolidays = DbTools.getSqlToList(sql).stream().map(e->e.get("id").toString()).collect(Collectors.toList());
            if (needRevokeHolidays.size() > 0){
                sql = "update uf_jcl_kq_qjjl_dt1 set cxqj=1 where id in ("+String.join(",",needRevokeHolidays)+")";
                DbTools.update(sql);
            }
        }

    }

}
