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 com.jay.monitor.data.server.utils.DataUtils;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * 告警数据缓存
 *
 * @author liukaixiong
 * @date 2021/9/8 - 10:57
 */
@Component
public class AlertDataCacheImpl implements AlertDataService {

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

    @Autowired
    protected IAlertPlatformProcess alertPlatformProcess;

    @Autowired
    protected IAlertRuleProcess alertRuleProcess;

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

    private final String PREFIX_PLATFORM = "p_";
    private final String PREFIX_RULE_PROJECT = "r_p_";
    private final String PREFIX_RULE_ID = "r_id_";

    public void refreshRuleCache(Map<String, Object> cacheMap) {
        AlertRuleConfig config = new AlertRuleConfig();
        config.setStatus(1);
        // 查找相关的项目
        List<AlertRuleConfig> alertRuleConfigList = alertRuleProcess.queryList(config);
        if (CollectionUtils.isNotEmpty(alertRuleConfigList)) {
            for (AlertRuleConfig alertRuleConfig : alertRuleConfigList) {
                refreshRuleInfoCache(cacheMap, alertRuleConfig);
                refreshRuleProjectCache(cacheMap, alertRuleConfig.getProject(), alertRuleConfig.getId());
            }
        }
    }

    private void refreshRuleProjectCache(Map<String, Object> cacheMap, String projectString, String ruleId) {
        List<String> projectList = DataUtils.getProjectList(projectString);
        for (String project : projectList) {
            Set<String> ruleIds =
                (Set<String>)cacheMap.computeIfAbsent(PREFIX_RULE_PROJECT + project, key -> new HashSet<>());
            ruleIds.add(ruleId);
        }
    }

    @Override
    public AlertRuleConfig getRuleId(String id) {
        return getCacheRuleId(id);
    }

    @Override
    public AlertPlatformConfig getAlertPlatform(String id) {
        return getCacheAlertPlatform(id);
    }

    @Override
    public void refreshPlatformId(String id) {
        if (StringUtils.isEmpty(id)) {
            return;
        }
        refreshAlertPlatformCache(id);
    }

    private void removeRuleIdCache(String ruleId) {
        AlertRuleConfig alertRule = getCacheRuleId(ruleId);
        if (alertRule != null) {
            cacheMap.remove(PREFIX_RULE_ID + ruleId);
            removeRuleProjectCache(alertRule.getProject(), ruleId);
        }
        logger.warn("强制停止告警规则 id : " + ruleId + " \t 规则名称 : " + alertRule.getRuleName());
    }

    private void removeRuleProjectCache(String projectString, String ruleId) {
        List<String> projectList = DataUtils.getProjectList(projectString);
        for (String project : projectList) {
            Set<String> ruleIds = (Set<String>)cacheMap.getOrDefault(PREFIX_RULE_PROJECT + project, new HashSet<>());
            ruleIds.remove(ruleId);
        }
    }

    /**
     * 强制更新规则
     *
     * @param alertRuleConfig
     */
    private void refreshRuleInfoCache(Map<String, Object> cacheMap, AlertRuleConfig alertRuleConfig) {
        if (alertRuleConfig == null || alertRuleConfig.getStatus() != 1) {
            return;
        }

        cacheMap.put(PREFIX_RULE_ID + alertRuleConfig.getId(), alertRuleConfig);
    }

    @Override
    public List<AlertRuleConfig> getRuleList(String project) {
        return getCacheRuleList(project);
    }

    @Override
    public void refreshRuleId(String ruleId) {
        AlertRuleConfig config = alertRuleProcess.queryById(ruleId);
        refreshRuleInfoCache(this.cacheMap, config);
    }

    /**
     * 强制关闭某些规则
     *
     * @param ruleId 规则编号
     */
    @Override
    public synchronized void forceCloseRule(String ruleId) {
        removeRuleIdCache(ruleId);
        AlertRuleConfig config = new AlertRuleConfig();
        config.setStatus(-1);
        config.setId(ruleId);
        alertRuleProcess.update(config);
    }

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

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

    /**
     * 从缓存中获取
     *
     * @param project
     * @return
     */
    private List<AlertRuleConfig> getCacheRuleList(String project) {
        Set<String> projectRuleList =
            (Set<String>)cacheMap.getOrDefault(PREFIX_RULE_PROJECT + project, new HashSet<>());
        return projectRuleList.stream().map(this::getCacheRuleId).collect(Collectors.toList());
    }

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

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

    private void refreshAlertPlatformCache(String id) {
        AlertPlatformConfig config = this.searchForceAlertPlatform(id);
        if (config == null) {
            cacheMap.remove(PREFIX_PLATFORM + id);
            logger.debug("平台编号:{} 清理完成!", id);
        } else {
            cacheMap.put(PREFIX_PLATFORM + id, config);
            logger.debug("平台编号:{} -> {} 刷新完成!", id, config.getAlertName());
        }
    }

    public void refreshAlertPlatformCache(Map<String, Object> cacheMap) {
        AlertPlatformConfig config = new AlertPlatformConfig();
        config.setStatus(1);
        List<AlertPlatformConfig> alertPlatformConfigs = alertPlatformProcess.queryList(config);
        if (CollectionUtils.isNotEmpty(alertPlatformConfigs)) {
            for (AlertPlatformConfig alertRuleConfig : alertPlatformConfigs) {
                cacheMap.put(PREFIX_PLATFORM + alertRuleConfig.getId(), alertPlatformConfigs);
            }
        }
    }

    /**
     * 缓存更新
     */
    @Override
    public void refreshCache() {
        try {
            int size = cacheMap.size() * 2;
            Map<String, Object> forceUpdateMap = new ConcurrentHashMap<>(Math.max(size, 16));

            refreshRuleCache(forceUpdateMap);

            refreshAlertPlatformCache(forceUpdateMap);

            // 将强制刷新的数据应用到缓存中
            this.cacheMap = forceUpdateMap;
            logger.info("触发刷新规则缓存!");
        } catch (Throwable e) {
            logger.error("缓存异常", e);
        }
    }

}
