package com.jay.monitor.data.server.report.alert;

import com.jay.monitor.data.server.models.store.AlertPlatformConfig;
import com.jay.monitor.data.server.models.store.AlertRuleConfig;
import com.jay.monitor.data.server.store.IAlertPlatformProcess;
import com.jay.monitor.data.server.store.IAlertRuleProcess;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

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

/**
 * 规则缓存工厂
 *
 * @author liukaixiong
 * @Email liukx@elab-plus.com
 * @date 2021/9/8 - 10:57
 */
@Component
public class RuleCacheFactory {

    private Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    protected IAlertPlatformProcess alertPlatformProcess;

    @Autowired
    protected IAlertRuleProcess alertRuleProcess;

    private Map<String, Object> cacheMap = new ConcurrentHashMap<>();

    private String prefix_platform = "p_";
    private String prefix_rule_project = "r_p_";
    private String prefix_rule_id = "r_id_";

    /**
     * 强制从源头获取
     *
     * @param project
     * @return
     */
    public List<AlertRuleConfig> searchRuleCacheList(String project) {
        AlertRuleConfig config = new AlertRuleConfig();
        config.setProject(project);
        config.setStatus(1);
        // 查找相关的项目
        List<AlertRuleConfig> alertRuleConfigList = alertRuleProcess.queryList(config);
        return alertRuleConfigList == null ? new ArrayList<>() : alertRuleConfigList;
    }

    /**
     * 强制关闭某些规则
     *
     * @param ruleId 规则编号
     */
    public synchronized void forceCloseRule(String ruleId) {
        AlertRuleConfig cacheRuleId = getCacheRuleId(ruleId);
        if (cacheRuleId != null) {
            cacheMap.remove(prefix_rule_id + ruleId);
            AlertRuleConfig config = new AlertRuleConfig();
            config.setStatus(-1);
            config.setId(ruleId);
            alertRuleProcess.update(config);
            logger.warn("强制停止告警规则 id : " + ruleId + " \t 规则名称 : " + cacheRuleId.getTitle());
        }
    }

    public AlertRuleConfig searchRuleCacheId(String id) {
        // 查找相关的项目
        return alertRuleProcess.queryById(id);
    }

    /**
     * 获取规则编号
     *
     * @param id
     * @return
     */
    public AlertRuleConfig getCacheRuleId(String id) {
        // 查找相关的项目
        return (AlertRuleConfig)cacheMap.computeIfAbsent(prefix_rule_id + id, k -> searchRuleCacheId(id));
    }

    /**
     * 从缓存中获取
     *
     * @param project
     * @return
     */
    public List<AlertRuleConfig> getCacheRuleList(String project) {
        return (List<AlertRuleConfig>)cacheMap
            .computeIfAbsent(prefix_rule_project + project, k -> searchRuleCacheList(project));
    }

    /**
     * 强制获取告警平台详情
     *
     * @param id
     * @return
     */
    public AlertPlatformConfig searchAlertPlatform(String id) {
        AlertPlatformConfig alertPlatformConfig = alertPlatformProcess.queryById(id);
        return alertPlatformConfig;
    }

    /**
     * 获取缓存中的平台数据
     *
     * @param id
     * @return
     */
    public AlertPlatformConfig getCacheAlertPlatform(String id) {
        return (AlertPlatformConfig)cacheMap.computeIfAbsent(prefix_platform + id, k -> this.searchAlertPlatform(id));
    }

    /**
     * 缓存更新
     */
    public void refreshCache() {
        try {
            int size = cacheMap.size() * 2;
            Map<String, Object> forceUpdateMap = new ConcurrentHashMap<>(Math.max(size, 16));
            cacheMap.forEach((key, val) -> {
                if (key.startsWith(prefix_rule_project)) {
                    // 处理告警规则
                    String project = key.split(prefix_rule_project)[1];
                    List<AlertRuleConfig> alertRuleConfigs = searchRuleCacheList(project);
                    forceUpdateMap.put(key, alertRuleConfigs);
                } else if (key.startsWith(prefix_rule_id)) {
                    String id = key.split(prefix_rule_id)[1];
                    AlertRuleConfig alertRuleConfigs = searchRuleCacheId(id);
                    forceUpdateMap.put(key, alertRuleConfigs);
                } else if (key.startsWith(prefix_platform)) {
                    // 处理告警平台
                    String id = key.split(prefix_platform)[1];
                    AlertPlatformConfig alertPlatformConfig = searchAlertPlatform(id);
                    forceUpdateMap.put(key, alertPlatformConfig);
                }
            });
            // 将强制刷新的数据应用到缓存中
            this.cacheMap = forceUpdateMap;
            logger.info("触发刷新规则缓存!");
        } catch (Throwable e) {
            logger.error("缓存异常", e);
        }
    }

}
