package org.jeecg.modules.stm.job;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.dto.message.MessageDTO;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.modules.message.entity.SysMessageTemplate;
import org.jeecg.modules.stm.metric.entity.MetricApiCfg;
import org.jeecg.modules.stm.metric.entity.MetricMonitorSet;
import org.jeecg.modules.stm.metric.entity.MetricReport;
import org.jeecg.modules.stm.metric.service.IMetricApiCfgService;
import org.jeecg.modules.stm.metric.service.IMetricMonitorSetService;
import org.jeecg.modules.stm.metric.service.IMetricReportService;
import org.jeecg.modules.system.service.ISysUserService;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Component
public class FxcAPIJob implements Job {
    @Autowired
    private IMetricApiCfgService metricApiCfgService;
    @Autowired
    private IMetricReportService metricReportService;
    @Autowired
    private ISysBaseAPI sysBaseAPI;
    @Autowired
    private ISysUserService sysUserService;
    @Autowired
    private IMetricMonitorSetService metricMonitorSetService;

    private static Map<String, MetricMonitorSet>  metricMonitorSetMap;

    @Override
    public void execute(JobExecutionContext jobExecutionContext) {
        setAllMetricSet();
        List<MetricApiCfg> metricApiCfgs = metricApiCfgService.list();
        try {
            for (MetricApiCfg cfgApi : metricApiCfgs) {
                getDataFromAPI(cfgApi);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void getDataFromAPI(MetricApiCfg cfgApi) {
        String url = cfgApi.getUrl();
        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);
        String data = response.getBody();
        Integer vtp = cfgApi.getValueType();
        String valueField = cfgApi.getValueField();
        if(vtp.intValue()==2) {
            Float val = jsonParser(data,valueField);
            float mult = cfgApi.getMult()==null?1f:cfgApi.getMult();
            val = val!=null?val.floatValue()*mult:0.0f;
            sendMessage(cfgApi,val);
        } else if(vtp.intValue()==1) {
            Double val = Double.parseDouble(data);
            val = val!=null?val.doubleValue()*cfgApi.getMult(): 0.0f;
            saveData(val,cfgApi.getMtrcNo());
            sendMessage(cfgApi,val);
        }
    }

    public void saveData(Double val,String mtrcNo) {
        MetricReport metricReport = new MetricReport();
        metricReport.setReporter("api");
        metricReport.setDes("系统通过接口获取");
        metricReport.setFillTime(new Date());
        metricReport.setMtrcNo(mtrcNo);
        metricReport.setFillVals(val.toString());
        metricReportService.save(metricReport);
    }

    private Float jsonParser(String jsonString,String valField) {
        try {
            ObjectMapper mapper = new ObjectMapper();
            JsonNode jsonNode = mapper.readTree(jsonString);
            JsonNode value = findValueForKey(jsonNode, valField);
            if (value != null) {
                if (value.isNumber()) {
                    return handleFloat(value.floatValue());
                } else {
                    System.out.println("Value is not a number.");
                }
            } else {
                System.out.println("Key '" + valField + "' not found.");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    //保留两位小数，
    private float handleFloat(float val) {
        BigDecimal number = new BigDecimal(val);
        BigDecimal roundedNumber = number.setScale(2, BigDecimal.ROUND_HALF_UP);
        return  roundedNumber.floatValue();
    }

    /**
     * 递归查找 JSON 对象中的键值对
     * @param jsonNode JSON 对象
     * @param key 要查找的键
     * @return 键对应的值，如果键不存在则返回 null
     */
    private static JsonNode findValueForKey(JsonNode jsonNode, String key) {
        if (jsonNode.isObject()) { // 如果当前节点是 JSON 对象
            if (jsonNode.has(key)) { // 如果当前对象包含要查找的键
                return jsonNode.get(key); // 返回键对应的值
            } else { // 如果当前对象不包含要查找的键
                // 递归查找当前对象的所有子节点
                for (JsonNode child : jsonNode) {
                    JsonNode value = findValueForKey(child, key);
                    if (value != null) {
                        return value;
                    }
                }
            }
        } else if (jsonNode.isArray()) { // 如果当前节点是 JSON 数组
            // 递归查找数组中的所有元素
            for (JsonNode child : jsonNode) {
                JsonNode value = findValueForKey(child, key);
                if (value != null) {
                    return value;
                }
            }
        }
        return null;
    }

    private Result<SysMessageTemplate> sendMessage(MetricApiCfg apiCfg,double val) {
        Result<SysMessageTemplate> result = new Result<SysMessageTemplate>();
        try {
            MessageDTO md = new MessageDTO();
            md.setToAll(false);
            md.setTitle("通知【"+apiCfg.getApiName()+"】");
            md.setTemplateCode("sys_ts_note");
            md.setToUser(apiCfg.getReceiver());
            md.setType("system");
            md.setFromUser("admin");
            Map<String,Object> data = new HashMap<>();
            data.put("ts_content",getContentStr(apiCfg,val));
            data.put("ts_date",getCurTimeStr());
            md.setData(data);
            sysBaseAPI.sendTemplateMessage(md);
            md.setType("email");
            sysBaseAPI.sendTemplateMessage(md);
            return result.success("消息发送成功！");
        } catch (Exception e) {
            log.error("发送消息出错", e.getMessage());
            return result.error500("发送消息出错！");
        }
    }

    private String getCurTimeStr() {
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String curTime = now.format(formatter);
        return curTime;
    }

    private String getContentStr(MetricApiCfg apiCfg,double val) {
        StringBuffer sb = new StringBuffer();

        String mtricNo = apiCfg.getMtrcNo();
        if(this.metricMonitorSetMap!=null) {
            MetricMonitorSet mSet = this.metricMonitorSetMap.get(mtricNo);
            sb.append("<br><hr>");
            sb.append("<div style='margin:10px'>");
            sb.append("<h5 style='color:red;font-weight:bold'>").append(mSet.getMtrcName()).append("【").append(val).append("】</h5>");
//            sb.append("<ul style='padding:5px'><li>").append("容忍值:").append("[").append(mSet.getTolVal()).append("]</li>");
//            sb.append("<li>").append("预警值:").append("[").append(mSet.getWarnVal()).append("]</li>");
//            sb.append("<li>").append("干预值:").append("[").append(mSet.getIntvVal()).append("]</li>");
//            sb.append("</li></ul>");
            String ret = getCurStr(mSet,val);
            sb.append(ret);
            sb.append("</div>");
        }
        return sb.toString();
    }

    private void setAllMetricSet() {
        QueryWrapper<MetricMonitorSet> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("coll_method", "2");
        //if (this.metricMonitorSetMap == null) {
            this.metricMonitorSetMap = new HashMap<>();
            List<MetricMonitorSet> list = metricMonitorSetService.list();
            for(MetricMonitorSet mSet : list) {
                this.metricMonitorSetMap.put(mSet.getMtrcNo(),mSet);
            }
        //}
    }

    private String getCurStr( MetricMonitorSet mSet,double val) {
        float tolVal = mSet.getTolVal().floatValue();
        float warnVal = mSet.getWarnVal().floatValue();
        float intvVal = mSet.getIntvVal().floatValue();
        StringBuilder sb = new StringBuilder();
        int flag =0;
        sb.append("<ul>");
        if(tolVal<intvVal) {
            if (val <= tolVal) {
                sb.append("<li>").append("当前值【").append(val).append("】").append("</li>");
                flag=1;
            }
            sb.append("<li>").append("容忍值:").append("[").append(tolVal).append("]").append("</li>");
            if (val <= warnVal) {
                sb.append("<li>").append("当前值【").append(val).append("】").append("</li>");
                flag=2;
            }
            sb.append("<li>").append("预警值:").append("[").append(warnVal).append("]").append("</li>");
            if (val <= intvVal) {
                sb.append("<li style='color:red'>").append("当前值【").append(val).append("】").append("</li>");
                flag=3;
            }
            sb.append("<li>").append("干预值:").append("[").append(intvVal).append("]").append("</li>");
            if (val>intvVal) {
                sb.append("<li style='color:red'>").append("当前值【").append(val).append("】").append("</li>");;
                flag=4;
            }
        } else {
            if (val>= tolVal) {
                sb.append("<li>").append("当前值【").append(val).append("】").append("</li>");
                flag=1;
            }
            sb.append("<li>").append("容忍值:").append("[").append(tolVal).append("]").append("</li>");
            if (val >= warnVal) {
                sb.append("<li>").append("当前值【").append(val).append("】").append("</li>");
                flag=2;
            }
            sb.append("<li>").append("预警值:").append("[").append(warnVal).append("]").append("</li>");
            if (val >= intvVal) {
                sb.append("<li style='color:red'>").append("当前值【").append(val).append("】").append("</li>");
                flag=3;
            }
            sb.append("<li>").append("干预值:").append("[").append(intvVal).append("]").append("</li>");
            if (val < intvVal) {
                sb.append("<li style='color:red'>").append("当前值【").append(val).append("】").append("</li>");
                flag=4;
            }
        }
        sb.append("</ul>");

       return sb.toString();
    }

    private void checkYesNoCallAPI( MetricMonitorSet mSet,MetricApiCfg apiCfg) {
        int freq = mSet.getCollFreq();
        LocalDate currentDate = LocalDate.now();
        LocalTime currentTime = LocalTime.now();
        LocalDate stDate = apiCfg.getStDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        //long days = ChronoUnit.DAYS.between(currentDate, stDate);

        int stHour = apiCfg.getStTime();
        int currentHour = currentTime.getHour();

        boolean ret = false;
        if(stHour < currentHour) {
            //return ret;
        }

        switch (freq) {
            case 1:
                ret = true;
                break;
            case 2:
                long weeks = ChronoUnit.WEEKS.between(currentDate, stDate);
                if(weeks>0) ret = true;
                break;
            case 3:
                long month = ChronoUnit.MONTHS.between(currentDate, stDate);
                if(month>0) ret = true;
                break;
            case 4:
                long monthq = ChronoUnit.MONTHS.between(currentDate, stDate);
                //if(monthq) ret = true;

                break;
            case 5:

                break;
            case 6:

                break;
            default:

                break;
        }


    }

}

