package com.cpp.web.service.alarm;

import ch.qos.logback.classic.Logger;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.cpp.common.utils.spring.SpringUtils;
import com.cpp.web.domain.Alarm.AbnormalAlarm;
import com.cpp.web.domain.enums.AlarmEnum;
import com.cpp.web.domain.enums.DataSourcesEnum;
import com.cpp.web.utils.LogUtil;
import lombok.Data;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;


/**
 * 告警日志类
 */
public class AlarmLog {

    //实时告警map
    private Map<String, AlarmDto> alarmDtoMap = new ConcurrentHashMap<>();

    private Logger logger = new AppenderFactory().getAppender();

    public static final AlarmLog getInstance() {
        return LazyHolder.INSTANCE;
    }

    private static class LazyHolder {
        private static final AlarmLog INSTANCE = new AlarmLog();
    }

    /**
     * 告警日志打印+存储
     *
     * @param alarmSource
     * @param alarmType
     * @param info
     * @param stationCode
     */
    public void info(DataSourcesEnum alarmSource, AlarmEnum alarmType, String info, String stationCode) {

        String key = alarmSource.getCode() + "_" + alarmType.getCode() + "_" + info + "_" + stationCode;
        if (alarmDtoMap.containsKey(key)) {
            alarmDtoMap.get(key).setUpdateTime(new Date());
        } else {
            AbnormalAlarm abnormalAlarm = new AbnormalAlarm(alarmSource, alarmType, info, stationCode);
            SpringUtils.getBean(AbnormalAlarmService.class).save(abnormalAlarm);
            AlarmDto alarmDto = new AlarmDto(abnormalAlarm, new Date());
            alarmDtoMap.put(key, alarmDto);
        }

        logger.info(LogUtil.format("【场站编号：{}】，【业务类型：{}-{}】，【告警内容：{}】", stationCode, alarmSource.getMessage(), alarmType.getMessage(), info));

    }


    @Data
    public class AlarmDto {
        private AbnormalAlarm abnormalAlarm;

        private Date updateTime;

        public AlarmDto(AbnormalAlarm abnormalAlarm, Date updateTime) {
            this.abnormalAlarm = abnormalAlarm;
            this.updateTime = updateTime;
        }
    }


    /**
     * 定时清理
     */
    public void eliminate() {
        List<String> keys = new ArrayList<>();
        List<AbnormalAlarm> abnormalAlarms = new ArrayList<>();

        //告警时效20分钟，20分钟内无重复告警将结束实时告警
        Date date = new Date(System.currentTimeMillis() - 1200000L);
        for (Map.Entry<String, AlarmDto> stringAlarmDtoEntry : alarmDtoMap.entrySet()) {
            AlarmDto alarmDto = stringAlarmDtoEntry.getValue();
            if (alarmDto.getUpdateTime().before(date)) {
                keys.add(stringAlarmDtoEntry.getKey());
                AbnormalAlarm abnormalAlarm = alarmDto.getAbnormalAlarm();
                abnormalAlarm.setEndTime(alarmDto.getUpdateTime());
                abnormalAlarms.add(abnormalAlarm);
            }
        }

        if (keys.size() > 0) {
            keys.forEach(k -> alarmDtoMap.remove(k));
            SpringUtils.getBean(AbnormalAlarmService.class).saveOrUpdateBatch(abnormalAlarms);
        }
    }


    /**
     * 初始化告警信息
     */
    public void initMap() {
        List<AbnormalAlarm> abnormalAlarms = SpringUtils.getBean(AbnormalAlarmService.class).list(Wrappers.lambdaQuery(AbnormalAlarm.class).select().isNull(AbnormalAlarm::getEndTime));
        for (AbnormalAlarm abnormalAlarm : abnormalAlarms) {
            String key = abnormalAlarm.getAlarmSource().getCode() + "_" + abnormalAlarm.getAlarmType().getCode() + "_" + abnormalAlarm.getMsg() + "_" + abnormalAlarm.getStationCode();
            alarmDtoMap.put(key, new AlarmDto(abnormalAlarm, new Date()));
        }
    }
}
