package org.jeecg.modules.dataVue.task;

import com.alibaba.druid.proxy.jdbc.NClobProxyImpl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.util.DateUtils;
import org.jeecg.common.util.ReflectHelper;
import org.jeecg.modules.dataVue.entity.Task;
import org.jeecg.modules.dataVue.entity.WarnHistory;
import org.jeecg.modules.dataVue.service.*;
import org.jeecg.modules.engineer.entity.BWellOwnEngineer;
import org.jeecg.modules.engineer.service.winform.CheckEngineerWarning;
import org.jeecg.modules.engineer.service.dataDiagnosticService.models.LtdRecord;
import org.jeecg.modules.engineer.service.dataDiagnosticService.data.DrillState;
import org.jeecg.modules.engineer.service.winform.data.MonitorAlarmRecord;
import org.jeecg.modules.engineer.service.winform.data.MonitorAlarmRecords;
import org.jeecg.modules.engineer.service.winform.data.RecordHashTable;
import org.jeecg.modules.warning.model.DrillInfoModel;
import org.jeecg.modules.warning.service.IFzqkService;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;

import java.lang.reflect.InvocationTargetException;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.text.ParseException;
import java.util.*;

/**
 * 示例带参定时任务
 *
 * @Author Scott
 */
@Slf4j
public class WarnHistoryJob implements Job {
    @Autowired
    IFzqkService iFzqkService;
    @Autowired
    IMasterService iLogicService;
    @Autowired
    ILtdSourceService iLtdSourceService;
    @Autowired
    IZjyService iZjyService;
    @Autowired
    ILjrbService iLjrbService;
    @Autowired
    IZjfzService iZjfzService;
    @Autowired
    ITaskService iTaskService;
    @Autowired
    IWarnHistoryService iWarnHistoryService;

    /**
     * 若参数变量名修改 QuartzJobController中也需对应修改
     */
    private String parameter;

    private String historyDayCount = "5";

    public void setParameter(String parameter) {
        this.parameter = parameter;
    }

    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        String jh = parameter.split(",")[0];
        boolean isLtd = parameter.split(",")[1].equals("1");
        String userId = parameter.split(",")[2];
        double x = 0;
        double y = 0;
        Result<HashMap<String, Object>> result = new Result();
        String sql = " select  xzb x, yzb y  "
                + " from v_scdt_jwxx t " +
                " where xzb is not null and yzb is not null "
                + String.format(" and jh = '%s' ", jh);
        List<Map<String, Object>> data = iLjrbService.querySql(sql, null);
        if (data.size() == 0) {
            sql = " select t2.sjjwzzbx x, t2.SJJWZZBY y from mv_azj01 t2 " +
                    " where sjjwzzbx is not null and sjjwzzby is not null "
                    + String.format(" and jh = '%s' ", jh);
            data = iZjfzService.querySql(sql, null);
        }
        if (data.size() > 0) {
            x = Double.parseDouble(data.get(0).get("X").toString());
            y = Double.parseDouble(data.get(0).get("Y").toString());
        }
        boolean hasCoor = x != 0 && y != 0;
        List<Map<String, Object>> date = null;
        if (isLtd) {
            String aTab = iLogicService.getTableCode(jh);
            String sql1 = "select *\n" +
                    "  from (select row_number() over(order by d desc) rn, d\n" +
                    "          from (select distinct (substr(time, 0, 10)) d from %s))\n" +
                    " where rn <= %s\n" +
                    " order by rn desc ";
            sql1 = String.format(sql1, aTab, historyDayCount);
            date = iLtdSourceService.querySql(sql1, null);
        } else {
            String sql1 = "select *\n" +
                    "  from (select d, row_number() over(order by d desc) rn\n" +
                    "          from (select distinct (to_char(sj, 'yyyy-mm-dd')) d\n" +
                    "                  from ZJYCS_%s t))\n" +
                    " where rn <= %s\n" +
                    " order by rn desc";
            sql = String.format(sql1, jh.replace('-', '_'), historyDayCount);
            date = iZjyService.querySql(sql, null);
        }

        Task warnTask = new Task();
        QueryWrapper<Task> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id", jh);
        queryWrapper.eq("del_flag", 0);
        Task exist = iTaskService.getOne(queryWrapper);
        if (exist == null) {
            warnTask.setId(jh);
            warnTask.setCreateBy(userId);
            warnTask.setCreateTime(new Date());
            warnTask.setDelFlag(0);
            warnTask.setStatus(0);
            warnTask.setJobClassName("org.jeecg.modules.dataVue.task.WarnHistoryJob");
            warnTask.setParameter("");
            warnTask.setDescription(jh + ",天数:" + date.size());
            iTaskService.save(warnTask);
        } else {
            warnTask = exist;
        }
        int minSpan = 5;
        int i = 1;
        String lastWarnRecord = "select max(warnTime) last from b_warnhistory where jh = '%s'  ";
        lastWarnRecord = String.format(lastWarnRecord, jh);
        List<Map<String, Object>> dt = iLogicService.querySql(lastWarnRecord, null);
        Date lastTaskExcuted = null;
        if (exist != null && exist.getDescription().split(",").length > 2) {
            try{
                lastTaskExcuted = DateUtils.parseDate(exist.getDescription().split(",")[2], "yyyy-MM-dd HH:mm:ss");
            } catch (Exception ex){
                ex.printStackTrace();
            }
        }
        if (dt.size() > 0 && dt.get(0) != null) {
            Date lastWarnDate = new Date(((Timestamp)dt.get(0).get("LAST")).getTime());
            if(lastWarnDate.after(lastTaskExcuted)){
                lastTaskExcuted = lastWarnDate;
            }
        }

        for (Map<String, Object> row : date) {
            String day = row.get("D").toString();
            if (isLtd) {
                Date today = null;
                try {
                    today = DateUtils.parseDate(day, "yyyy-MM-dd");
                } catch (ParseException e) {
                    e.printStackTrace();
                }
                today = org.apache.commons.lang.time.DateUtils.addMinutes(today, minSpan);
                long startTime = System.currentTimeMillis();
                int k = 0;
                while (DateUtils.formatDate(today, "yyyy-MM-dd").equals(day)) {
                    if(lastTaskExcuted != null && today.before(lastTaskExcuted)){
                        today = org.apache.commons.lang.time.DateUtils.addMinutes(today, minSpan);
                        continue;
                    }
                    if(today.after(new Date())){
                        break;
                    }
                    List<WarnHistory> warnList = new ArrayList<>();
                    if (hasCoor) {
                        // TODO: 修改 jsStart
                        Map<String, List<DrillInfoModel>> fzqk = iFzqkService.Calculate(5000, jh,
                                "", "", 0, x, y);
                        final DrillInfoModel maxDanger = new DrillInfoModel();
                        maxDanger.setCorr(-1);
                        fzqk.forEach((s, list) -> {
                            list.forEach(d -> {
                                if (Double.compare(d.getCorr(), maxDanger.getCorr()) > 0) {
                                    try {
                                        BeanUtils.copyProperties(maxDanger, d);
                                    } catch (IllegalAccessException e) {
                                        e.printStackTrace();
                                    } catch (InvocationTargetException e) {
                                        e.printStackTrace();
                                    }
                                }
                            });
                        });
                        String sql1 = String.format("select * from jsra where jh ='%s' and sgxh= '%s' ",
                                maxDanger.getAlbh(), maxDanger.getJh());
                        if (maxDanger.getCorr() != 0) {
                            List<Map<String, Object>> caseContent = iZjfzService.querySql(sql1, null);
                            if (caseContent.size() > 0) {
                                Map<String, Object> first = caseContent.get(0);
                                WarnHistory record = new WarnHistory();
                                record.source = "复杂情况";
                                record.jh = maxDanger.getAlbh() + "(案例井)";
                                record.catogary = maxDanger.getFzmc();
                                record.requestStart = new Date();
                                record.warnTime = today;
                                record.jcrq = null;
                                record.bjnr = NullOrStr(first.get("FSJGJYY"));
                                record.clfs = NullOrStr(first.get("SGCLGK"));
                                record.dsjs = NullOrStr(first.get("DSJS"));
                                record.zjzh = NullOrStr(first.get("ZJZH"));
                                record.serverCost = System.currentTimeMillis() - startTime;
                                record.key = maxDanger.getJh() + maxDanger.getAlbh();
                                warnList.add(record);
                            }
                        }
                    }

                    MonitorAlarmRecords warn = EngineerWarn(jh, today);
                    for (MonitorAlarmRecord m : warn) {
                        WarnHistory record = new WarnHistory();
                        record.source = "工程预警";
                        record.jh = jh;
                        record.catogary = m._name;
                        record.requestStart = new Date();
                        record.warnTime = today;
                        record.jcrq = null;
                        record.bjnr = StringUtils.isEmpty(m.warnMsg) ? "" : m.warnMsg.replace("<br/>", "\r\n");
                        record.clfs = "";
                        record.dsjs = Double.toString(m._realDepthEnd);
                        record.serverCost = System.currentTimeMillis() - startTime;
                        record.key = Double.toString(m._realDepthEnd) + m._name + Double.toString(m._realDepthEnd);
                        warnList.add(record);
                    }

                    today = org.apache.commons.lang.time.DateUtils.addMinutes(today, minSpan);
                    iWarnHistoryService.saveBatch(warnList);
                    if (k++ % 5 == 0) {
                        warnTask.setDescription(jh + ",天数:" + Integer.toString(i) + "/" + date.size() + ", " + DateUtils.formatDate(today, "yyyy-MM-dd HH:mm:ss"));
                        iTaskService.updateById(warnTask);
                        System.out.println("正在执行任务：" + warnTask.getDescription());
                    }
                }
            } else {
                List<WarnHistory> zjyList = new ArrayList<>();
                String t = String.format("ZJYCS_%s_BJ", jh.replace('-', '_'));
                long subStatic = System.currentTimeMillis();
                // region
                String sql2 = " with t1 as (\n" +
                        "                             select  sj, bjlx, to_char(sj, 'yyyyMMDD') || bjlx || '_' ||substr(bjxx, 0, 12)  bjpart, bjxx " +
                        "           from %s\n  " +
                        //"               where sj > to_date('%s', 'yyyy-MM-dd hh24:mi:ss') " +
                        "                        ),\n" +
                        "\n" +
                        "                        tt1 as (\n" +
                        "                        select row_number() over (partition by  bjpart order by sj ) pn,  t1.* from t1),\n" +
                        "\n" +
                        "                        tt5 as (\n" +
                        "                        select bjpart, max(pn) maxPn from tt1 group by bjpart  ),\n" +
                        "\n" +
                        "                        tt3 as (\n" +
                        "                        select  tt2.sj nSj, tt5.maxpn, tt1.* from tt1 \n" +
                        "                        left join tt1 tt2 on tt2.pn = tt1.pn - 1 and tt1.bjpart = tt2.bjpart\n" +
                        "                        left join tt5 on tt5.bjpart = tt1.bjpart),\n" +
                        "\n" +
                        "                        tt6 as(\n" +
                        "                        select tt3.sj , tt3.nsj , round(to_number(tt3.sj - tt3.nsj)* 24 * 60 ) diffM, tt3.pn, tt3.maxpn, tt3.bjlx,  bjPart, tt3.bjxx  from tt3 \n" +
                        "                        order by bjpart, pn),\n" +
                        "                        tt9 as (\n" +
                        "                        select * from tt6  \n" +
                        "                        where diffM > 8 or maxpn = pn)\n" +
                        "\n" +
                        "                            select *\n" +
                        "                              from tt9\n" +
                        "                              WHERE TO_CHAR(SJ, 'yyyy-MM-dd') = '%s' \n" +
                        "                             order by sj  ";
                // endregion
                String lastZjyTime = day;
                sql2 = String.format(sql2, t, lastZjyTime);
                List<Map<String, Object>> warn = iZjyService.querySql(sql2, null);
                warn.forEach(k -> {
                    WarnHistory record = new WarnHistory();
                    record.source = "钻井液";
                    record.catogary = GetZjyCatogaryStr(k.get("BJLX").toString());
                    record.jh = jh;
                    record.requestStart = new Date();
                    try {
                        record.warnTime = org.jeecg.common.util.DateUtils.parseDate(k.get("SJ").toString(), "yyyy-MM-dd HH:mm:ss");
                    } catch (ParseException e) {
                        e.printStackTrace();
                    }
                    record.jcrq = null;
                    record.bjnr = k.get("BJXX").toString();
                    record.clfs = "";
                    record.dsjs = null;
                    record.serverCost = System.currentTimeMillis() - subStatic;
                    record.key = k.get("SJ") + "_" + k.get("BJLX");
                    zjyList.add(record);
                });
                iWarnHistoryService.saveBatch(zjyList);
            }
            warnTask.setUpdateBy(Integer.toString(i) + "/" + data.size());
            iTaskService.updateById(warnTask);
            i++;
        }
        warnTask.setUpdateTime(new Date());
        warnTask.setStatus(1);
        iTaskService.updateById(warnTask);
    }


    private String GetZjyCatogaryStr(String bjlx) {
        switch (bjlx) {
            case "0":
                return "门限报警";
            case "1":
                return "溢流报警";
            case "2":
                return "井漏报警";
            case "3":
                return "异常报警";
            default:
                return "未分类";
        }
    }

    private String NullOrStr(Object src) {
        if (src == null) {
            return null;
        } else {
            return src.toString();
        }
    }

    private String GetNClob(Object src) {
        String result = "";
        if (src instanceof NClobProxyImpl) {
            try {
                result = ((NClobProxyImpl) src).getSubString(1, (int) ((NClobProxyImpl) src).length());
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    /**
     * @param jh
     * @param ltdTime
     */
    private MonitorAlarmRecords EngineerWarn(String jh, Date ltdTime) {
        List<Map<String, Object>> list = iLogicService.querySql(
                String.format("select  id, create_by, create_time, update_by, update_time, jh, large_text largeText from b_wellownEngineer where jh ='%s'", jh), null);
        BWellOwnEngineer template = new BWellOwnEngineer();
        if (list.size()==0){
            //如果不存在该井的配置参数就去默认参数配置
            list = iLogicService.querySql(
                    String.format("select  id, create_by, create_time, update_by, update_time, jh, large_text largeText from b_wellownEngineer where jh = '默认' ", jh), null);
        }
        if (list.size() == 0) {
            return null;
        }
        template.setLargeText(GetNClob(list.get(0).get("LARGETEXT")));

        CheckEngineerWarning checkLogic = new CheckEngineerWarning(template);
        MonitorAlarmRecords monitorAlarmRecords = new MonitorAlarmRecords();
        DrillState ds = DrillState.None;
        String aTab = iLogicService.getTableCode(jh);
        String sql = "select * from %s where time >= '%s' and time <= '%s' ";

        sql = String.format(sql, aTab,
                DateFormatUtils.format(org.apache.commons.lang.time.DateUtils.addMinutes(ltdTime, -30), "yyyy-MM-dd HH:mm:ss"),
                DateFormatUtils.format(ltdTime, "yyyy-MM-dd HH:mm:ss"));

        List<Map<String, Object>> table = iLtdSourceService.querySql(sql, null);
        List<LtdRecord> ltdList = ReflectHelper.transList2Entrys(table, LtdRecord.class);
        for (LtdRecord item : ltdList) {
            RecordHashTable recordHashTable = CheckEngineerWarning.LtdToRecordHashTable(item);
            HashMap<String, Object> rv = checkLogic.Analyse(recordHashTable, monitorAlarmRecords, ds);
            ds = (DrillState) rv.get("ds");
        }
        for (int i = 0; i < monitorAlarmRecords.size(); i++) {
            MonitorAlarmRecord r = monitorAlarmRecords.get(i);
            r.SetAlarmMsg(i + 1, jh);
        }

        return monitorAlarmRecords;
    }
}
