package com.inspect.statistics;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.common.utils.CollectionUtils;
import com.inspect.base.core.utils.StringUtils;
import com.inspect.base.redis.service.RedisService;
import com.inspect.partrolresult.client.WebsocketService;
import com.inspect.partrolresult.domain.PatrolResult;
import com.inspect.partrolresult.mapper.PatrolResultMapper;
import com.inspect.statistics.domain.StaticsCompareAlarm;
import com.inspect.statistics.domain.TaskStatisticsConfig;
import com.inspect.statistics.mapper.StatisticsAlarmMsgMapper;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import javax.annotation.Resource;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

@Service
public class ResultStatistics {
    private final Logger logger = LoggerFactory.getLogger(ResultStatistics.class);
    @Resource
    PatrolResultMapper resultMapper;
    @Resource
    WebsocketService websocketService;
    @Resource
    RedisService redisService;
    @Resource
    StatisticsAlarmMsgMapper alarmMsgMapper;
    public static final String DONE_LINE_ID_SET_KEY = "done_result_line_set_";

    public void compare(PatrolResult result) {
        logger.info("[COMPARE] CALL COMPARE TO RESULT");
        (new Thread(() -> {
            try {
                doCompare(result);
            } catch (Exception e) {
                logger.error("CALL COMPARE EXCEPTION: {}", e.getMessage());
            }

        })).start();
    }

    public void doCompare(PatrolResult result) {
        String taskCode = result.getTaskCode();
        TaskStatisticsConfig config = queryConfig(taskCode);
        if (null == config) {
            logger.info("[COMPARE] NO BELONGING TO COMPARE TASK, CODE: {}", taskCode);
        } else if (StringUtils.isBlank(result.getValue())) {
            logger.info("[COMPARE] NO VALUE TO COMPARE TASK, CODE: {}", taskCode);
        } else {
            List<PatrolResult> patrolResults = this.queryTaskPatrolList(result);
            logger.info("[COMPARE] ANALYSIS CODE: {}, SIZE OF PATROL RESULT: {}", result.getTaskCode(), patrolResults.size());
            Integer deviceNum = queryTaskDeviceNum(taskCode);
            logger.info("[COMPARE] ANALYSIS SIZE OF DEVICE: {}", deviceNum);
            if (deviceNum > patrolResults.size()) {
                logger.info("[COMPARE] TASK PATROL NO FINISHED YET, PLEASE WAITING! CODE: {}", result.getTaskCode());
            } else {
                RedisTemplate<String, Long> redisTemplate = this.redisService.redisTemplate;
                patrolResults = (List) patrolResults.stream().filter((r) -> {
                    return Boolean.FALSE.equals(redisTemplate.opsForSet().isMember(handleKey(DONE_LINE_ID_SET_KEY), r.getLineId()));
                }).collect(Collectors.toList());
                logger.info("[COMPARE] SIZE OF REMOVE DUPLICATES: {}", patrolResults.size());
                if (deviceNum > patrolResults.size()) {
                    logger.info("[COMPARE] 2 TASK PATROL NO FINISHED YET, PLEASE WAITING! CODE: {}", result.getTaskCode());
                } else {
                    logger.info("[COMPARE] ALARM PATROL LIST: {} \n", JSONObject.toJSONString(patrolResults));
                    boolean isWarning = statisticsCompare(patrolResults, config);
                    Boolean exist = redisTemplate.hasKey(handleKey(DONE_LINE_ID_SET_KEY));
                    patrolResults.forEach((r) -> {
                        redisTemplate.opsForSet().add(handleKey(DONE_LINE_ID_SET_KEY), r.getLineId());
                    });
                    if (Boolean.FALSE.equals(exist)) {
                        redisTemplate.opsForSet().getOperations().expire(handleKey(DONE_LINE_ID_SET_KEY), 24L, TimeUnit.HOURS);
                    }

                    if (isWarning) {
                        JSONObject handleMsg = handleMsg(result.getTaskName(), config.getMsg());
                        logger.warn("[COMPARE] ALARM INFO DETECTED, PUSH TO FRONT: {}", handleMsg);
                        sendWarningMsg(handleMsg);
                        saveMsg(patrolResults, config);
                    }
                }
            }
        }
    }

    public static String handleKey(String key) {
        String today = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        return key + today;
    }

    public JSONObject handleMsg(String taskName, String msg) {
        JSONObject data = new JSONObject();
        data.put("taskName", taskName);
        data.put("msg", msg);
        JSONObject webMsg = new JSONObject();
        webMsg.put("event", "task_statistics_notify");
        webMsg.put("data", data);
        return webMsg;
    }

    public boolean statisticsCompare(List<PatrolResult> list, TaskStatisticsConfig config) {
        boolean result = false;
        //qinyl
//      switch(null.$SwitchMap$com$dliip$statistics$StatisticsType[StatisticsType.getByType(config.getType()).ordinal()]) {
//      case 1:
//      case 2:
//         result = this.diffEquals(list);
//         break;
//      case 3:
//      case 4:
//      case 5:
//         result = this.diffThreshold(list, config.getThreshold());
//         break;
//      case 6:
//         result = this.handleDiffTime(list, config.getThreshold());
//         break;
//      case 7:
//         PatrolResult patrolResult = (PatrolResult)list.get(0);
//         result = this.handleMeterTimes(Integer.valueOf(Integer.parseInt(config.getThreshold())), patrolResult.getDeviceId(), patrolResult.getPatroldeviceCode());
//         break;
//      default:
//         this.logger.warn("数据对比分析，对比数据时，type:{}，不在处理范围内，不予处理", config.getType());
//      }

        return result;
    }

    private boolean handleDiffTime(List<PatrolResult> list, String threshold) {
        PatrolResult patrolResult = list.get(0);
        String diffTimeStr = this.redisService.getCacheObject("sys_config:statistics_difftime_time");
        long diffTime = Long.parseLong(diffTimeStr);
        String taskCode = patrolResult.getTaskCode();
        List<PatrolResult> patrolResults = this.resultMapper.queryDiffTimeResult(taskCode, diffTime);
        if (patrolResults.size() < 2) {
            return false;
        } else {
            PatrolResult maxResult = patrolResults.get(0);
            PatrolResult minResult = patrolResults.get(patrolResults.size() - 1);
            BigDecimal maxValue = new BigDecimal(maxResult.getValue());
            BigDecimal minValue = new BigDecimal(minResult.getValue());
            BigDecimal subtract = maxValue.subtract(minValue);
            BigDecimal thresholdDecimal = new BigDecimal(threshold);
            return subtract.compareTo(thresholdDecimal) > 0;
        }
    }

    public boolean handleMeterTimes(Integer num, String deviceId, String patrolDeviceCode) {
        boolean warning = true;
        List<PatrolResult> list = this.resultMapper.queryNumTypeResult(num, deviceId, patrolDeviceCode);
        if (CollectionUtils.isEmpty(list)) {
            this.logger.warn("表计几次内不发生变化对比，未查询到巡视结果，不予处理");
            return false;
        } else {
            if (list.size() < num) {
                warning = false;
            } else {
                String firstValue = list.get(0).getValue();

                for (int i = 1; i < list.size(); ++i) {
                    String value = list.get(i).getValue();
                    if (!firstValue.equals(value)) {
                        warning = false;
                        break;
                    }
                }
            }

            return warning;
        }
    }

    public void sendWarningMsg(JSONObject msg) {
        this.websocketService.parseMessage(msg.toString());
    }

    public List<PatrolResult> queryTaskPatrolList(PatrolResult result) {
        PatrolResult param = new PatrolResult();
        param.setCreateTime(result.getCreateTime());
        param.setTaskCode(result.getTaskCode());
        return this.resultMapper.queryOneTaskResult(param);
    }

    public Integer queryTaskDeviceNum(String taskCode) {
        return this.resultMapper.queryTaskDeviceNum(taskCode);
    }

    public TaskStatisticsConfig queryConfig(String taskCode) {
        return this.resultMapper.selectStatisticsTaskConfigList(taskCode);
    }

    public boolean diffEquals(List<PatrolResult> resultList) {
        boolean result = false;

        for (PatrolResult source : resultList) {

            for (PatrolResult targetResult : resultList) {
                String value = source.getValue();
                String resultValue = targetResult.getValue();
                if (!StringUtils.equals(value, resultValue)) {
                    result = true;
                }
            }
        }

        return result;
    }

    public boolean diffThreshold(List<PatrolResult> resultList, String threshold) {
        if (StringUtils.isBlank(threshold)) {
            this.logger.info("阈值为空，不予对比");
            return false;
        } else {

            for (PatrolResult result : resultList) {

                for (PatrolResult targetResult : resultList) {
                    String value = result.getValue();
                    String resultValue = targetResult.getValue();

                    try {
                        BigDecimal sourceValue = new BigDecimal(value);
                        BigDecimal targetValue = new BigDecimal(resultValue);
                        BigDecimal thresholdDecimal = new BigDecimal(threshold);
                        if (targetValue.subtract(sourceValue).abs().compareTo(thresholdDecimal) > 0) {
                            this.logger.info("差值阈值对比，超过阈值，告警");
                            return true;
                        }
                    } catch (Exception var12) {
                        this.logger.warn("结果不为数值，不予对比");
                        return false;
                    }
                }
            }

            return false;
        }
    }

    public void saveMsg(List<PatrolResult> patrolResults, TaskStatisticsConfig config) {
        List<String> deviceNameList = new ArrayList<>();
        String recognitionType = "";
        String taskName = "";

        PatrolResult r;
        for (Iterator<PatrolResult> iterator = patrolResults.iterator(); iterator.hasNext(); taskName = r.getTaskName()) {
            r = iterator.next();
            if (!deviceNameList.contains(r.getDeviceName())) {
                deviceNameList.add(r.getDeviceName());
            }

            recognitionType = r.getRecognitionType();
        }

        this.logger.info("数据对比分析告警之前获取的点位名称列表，{}", JSONObject.toJSONString(deviceNameList));
        String deviceName = String.join(StringUtils.COMMA, deviceNameList);
        StaticsCompareAlarm alarm = new StaticsCompareAlarm();
        alarm.setAlarmMsg(config.getMsg());
        alarm.setTaskName(taskName);
        alarm.setDeviceName(deviceName);
        alarm.setRecognitionType(recognitionType);
        alarm.setTime(new Date());
        this.logger.info("数据对比分析告警入库，{}", JSONObject.toJSONString(alarm));
        this.alarmMsgMapper.saveAlarmMsg(alarm);
    }
}
