package com.zd.alarm.utils;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.zd.alarm.domain.AlarmLog;
import com.zd.alarm.service.IAlarmLogService;
import com.zd.common.core.utils.DateUtils;
import com.zd.system.api.alarm.domain.AlarmEntrty;
import com.zd.system.api.alarm.domain.Routes;
import com.zd.system.api.alarm.domain.SendTypes;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.validation.constraints.NotNull;
import java.util.*;

/**
 * 报警工具类
 * @author liubo
 */
@Component
@EnableScheduling
public class AlarmUtil {
    private static final Logger logger = LoggerFactory.getLogger(AlarmUtil.class);

    @Value("${alarm.host}")
    private String alarmUrl ;

    @Value("${alarm.retry}")
    private Integer retryCount ;

    @Autowired
    private IAlarmLogService alarmLogService;


    /**
     * 链接超时 项目启动会失败
     */
    @PostConstruct
    private void alarmInint(){
        sendGet(Routes.SystemStatusSnapshot);
        sendPost(new AlarmEntrty(Routes.NoticePush, new String[]{"18681887295"}, SendTypes.Call+"","启动项目电话报警服务测试！"));
    }

    /**
     * 发送语音报警对接功能
     */
    public Map sendPost(AlarmEntrty alarmEntrty) {
        logger.info("语音报警发送内容：" + alarmEntrty.toString());

        String url = alarmUrl + alarmEntrty.getRoute().getUrl();

        String result = HttpUtil.post(url, alarmEntrty.toString());

        logger.info("语音报警发送结果：" + result);
        Map<String, String> map = JSONObject.parseObject(result, Map.class);
        return map;
    }

    /**
     * 发送除语音报警 的其他功能
     */
    public String sendGet(@NotNull Routes route){
        return HttpUtil.get(alarmUrl + route.getUrl(), 3000);
    }



    /**
     * 定时检测 重试
     */
    @Scheduled(fixedRate=60 * 1000)
    public void timerCount(){

        Map<String, Object> params = new HashMap<>();
        params.put("retryCount", retryCount);
        params.put("date", DateUtils.getNowDate());
        List<AlarmLog> alarmLogs = alarmLogService.selectNoBackAlarmLogList(params);
        if(CollectionUtils.isNotEmpty(alarmLogs)){
            String data = sendGet(Routes.NoticeResult);
            List<Map> datas = JSONObject.parseArray(data, Map.class);
            if(CollectionUtils.isNotEmpty(datas)){

                Date date;
                List<String> failPhones = new ArrayList<>();
                for (AlarmLog alarmLog : alarmLogs) {
                    for (Map map : datas) {

                        if("电话".equals(map.get("method")) && alarmLog.getPhone().equals(map.get("to")) && alarmLog.getNotice().equals(map.get("notice"))){
                            date = DateUtil.parse(map.get("time")+ "");
                            Long timer = DateUtil.between(date, alarmLog.getCreateTime(), DateUnit.MINUTE, false);

                            // 此处 > 0 校验 电话报警发送在日志记录之前
                            // < 30 报警在 30 分钟只能完成，超过则不发
                            if(timer <= 0 && timer > -30){
                                alarmLog.setIsBack(alarmLog.getIsBack() + 1);
                                alarmLog.setStatus(map.get("status")+ "");
                                alarmLog.setMethod(map.get("method")+"");
                                alarmLog.setUpdateTime(DateUtils.getNowDate());
                                alarmLogService.updateAlarmLog(alarmLog);

                                if("失败".equals(map.get("status"))){
                                    System.out.println("重发数据： "+  alarmLog.toString());
                                    // TODO 运行异常 需记录 重拨ID或手机号 避免一次运行多次拨号
                                    if(!failPhones.contains(alarmLog.getPhone())){
                                        failPhones.add(alarmLog.getPhone());
                                        sendPost(new AlarmEntrty(Routes.NoticePush, new String[]{alarmLog.getPhone()}, SendTypes.Call+"", alarmLog.getNotice()));
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
