package com.common.service;

import com.common.entity.RuleHitTimeDTO;
import com.common.mapper.NormalizeRuleStatsMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

@Slf4j
@Service
public class NormalizeRuleHitTimeService {

    @Autowired
    private NormalizeRuleStatsMapper normalizeRuleStatsMapper;

    // 用于缓存最新的命中时间，避免重复查询
    private final Map<Long, LocalDateTime> ruleLatestHitCache = new ConcurrentHashMap<>();

    // 记录上次执行时间
    private LocalDateTime lastExecutionTime;


    public void updateRuleHitTimeTask() {
        long startTime = System.currentTimeMillis();
        log.info("开始执行泛化规则命中时间更新任务，时间：{}", LocalDateTime.now());

        try {
            // 执行更新逻辑
            int updatedCount = updateNormalizeRuleHitTime();

            long endTime = System.currentTimeMillis();
            log.info("泛化规则命中时间更新任务完成，更新规则数：{}，耗时：{}ms",
                    updatedCount, (endTime - startTime));

            // 更新上次执行时间
            lastExecutionTime = LocalDateTime.now();

        } catch (Exception e) {
            log.error("泛化规则命中时间更新任务执行失败", e);

        }
    }

    /**
     * 更新泛化规则命中时间
     * @return 更新的规则数量
     */
    public int updateNormalizeRuleHitTime() {
        // 1. 获取当天开始时间（用于过滤当天数据）
        LocalDateTime todayStart = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);

        // 2. 从两个标准化表中统计最新命中时间
        List<RuleHitTimeDTO> normalDataStats = normalizeRuleStatsMapper
                .selectMaxHitTimeFromNormalData(todayStart);
        List<RuleHitTimeDTO> alarmDataStats = normalizeRuleStatsMapper
                .selectMaxHitTimeFromNormalAlarm(todayStart);

        log.info("从 syslog_normal_data 表统计到 {} 条规则命中记录",
                normalDataStats.size());
        log.info("从 syslog_normal_alarm 表统计到 {} 条规则命中记录",
                alarmDataStats.size());

        // 3. 合并两个统计结果，取每个规则的最新命中时间
        Map<Long, LocalDateTime> ruleMaxHitTimeMap = mergeRuleHitTimes(
                normalDataStats, alarmDataStats
        );

        // 4. 获取所有启用状态的规则ID
        List<Long> activeRuleIds = normalizeRuleStatsMapper.selectActiveRuleIds();
        log.info("当前启用状态的规则数量：{}", activeRuleIds.size());

        // 5. 批量更新规则的最新命中时间
        int updatedCount = batchUpdateRuleHitTime(activeRuleIds, ruleMaxHitTimeMap);

        // 6. 更新缓存
        updateRuleHitCache(ruleMaxHitTimeMap);

        return updatedCount;
    }

    /**
     * 合并两个表的统计结果，取每个规则的最新命中时间
     */
    private Map<Long, LocalDateTime> mergeRuleHitTimes(
            List<RuleHitTimeDTO> normalDataStats,
            List<RuleHitTimeDTO> alarmDataStats
    ) {
        Map<Long, LocalDateTime> resultMap = new HashMap<>();

        // 处理 syslog_normal_data 表统计结果
        if (!CollectionUtils.isEmpty(normalDataStats)) {
            for (RuleHitTimeDTO dto : normalDataStats) {
                if (dto.getNormalizeRuleId() != null && dto.getMaxLogTime() != null) {
                    LocalDateTime currentMax = resultMap.get(dto.getNormalizeRuleId());
                    if (currentMax == null || dto.getMaxLogTime().isAfter(currentMax)) {
                        resultMap.put(dto.getNormalizeRuleId(), dto.getMaxLogTime());
                    }
                }
            }
        }

        // 处理 syslog_normal_alarm 表统计结果
        if (!CollectionUtils.isEmpty(alarmDataStats)) {
            for (RuleHitTimeDTO dto : alarmDataStats) {
                if (dto.getNormalizeRuleId() != null && dto.getMaxLogTime() != null) {
                    LocalDateTime currentMax = resultMap.get(dto.getNormalizeRuleId());
                    if (currentMax == null || dto.getMaxLogTime().isAfter(currentMax)) {
                        resultMap.put(dto.getNormalizeRuleId(), dto.getMaxLogTime());
                    }
                }
            }
        }

        log.info("合并后需要更新的规则数量：{}", resultMap.size());
        return resultMap;
    }

    /**
     * 批量更新规则命中时间
     */
    private int batchUpdateRuleHitTime(
            List<Long> activeRuleIds,
            Map<Long, LocalDateTime> ruleMaxHitTimeMap
    ) {
        if (CollectionUtils.isEmpty(activeRuleIds)) {
            return 0;
        }

        int updatedCount = 0;
        int batchSize = 1000; // 每批处理1000条
        int totalBatches = (activeRuleIds.size() + batchSize - 1) / batchSize;

        log.info("开始批量更新，规则总数：{}，分批数：{}", activeRuleIds.size(), totalBatches);

        for (int i = 0; i < totalBatches; i++) {
            int fromIndex = i * batchSize;
            int toIndex = Math.min(fromIndex + batchSize, activeRuleIds.size());
            List<Long> batchRuleIds = activeRuleIds.subList(fromIndex, toIndex);

            // 处理当前批次
            int batchUpdated = processBatchUpdate(batchRuleIds, ruleMaxHitTimeMap);
            updatedCount += batchUpdated;

            log.debug("第 {} 批处理完成，更新 {} 条规则", i + 1, batchUpdated);

            // 每处理完一批，稍作停顿，避免数据库压力过大
            if (i < totalBatches - 1) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    log.warn("批量更新任务被中断");
                }
            }
        }

        return updatedCount;
    }

    /**
     * 处理单个批次的更新
     */
    private int processBatchUpdate(
            List<Long> batchRuleIds,
            Map<Long, LocalDateTime> ruleMaxHitTimeMap
    ) {
        int batchUpdated = 0;

        for (Long ruleId : batchRuleIds) {
            LocalDateTime maxHitTime = ruleMaxHitTimeMap.get(ruleId);
            if (maxHitTime != null) {
                // 检查缓存中是否有更晚的时间
                LocalDateTime cachedTime = ruleLatestHitCache.get(ruleId);
                if (cachedTime == null || maxHitTime.isAfter(cachedTime)) {
                    // 执行更新
                    int updated = normalizeRuleStatsMapper.updateRuleHitTime(ruleId, maxHitTime);
                    if (updated > 0) {
                        batchUpdated++;
                    }
                }
            }
        }

        return batchUpdated;
    }

    /**
     * 更新命中时间缓存
     */
    private void updateRuleHitCache(Map<Long, LocalDateTime> ruleMaxHitTimeMap) {
        ruleMaxHitTimeMap.forEach((ruleId, hitTime) -> {
            LocalDateTime cachedTime = ruleLatestHitCache.get(ruleId);
            if (cachedTime == null || hitTime.isAfter(cachedTime)) {
                ruleLatestHitCache.put(ruleId, hitTime);
            }
        });

        // 清理过期的缓存（超过1天）
        cleanupExpiredCache();
    }

    /**
     * 清理过期缓存
     */
    private void cleanupExpiredCache() {
        LocalDateTime oneDayAgo = LocalDateTime.now().minusDays(1);
        Iterator<Map.Entry<Long, LocalDateTime>> iterator = ruleLatestHitCache.entrySet().iterator();

        int removedCount = 0;
        while (iterator.hasNext()) {
            Map.Entry<Long, LocalDateTime> entry = iterator.next();
            if (entry.getValue().isBefore(oneDayAgo)) {
                iterator.remove();
                removedCount++;
            }
        }

        if (removedCount > 0) {
            log.debug("清理了 {} 条过期缓存记录", removedCount);
        }
    }

    /**
     * 获取规则最新命中时间（缓存中）
     */
    public LocalDateTime getLatestHitTime(Long ruleId) {
        return ruleLatestHitCache.get(ruleId);
    }

    /**
     * 手动触发更新（可用于测试或紧急更新）
     */
    public int triggerManualUpdate() {
        log.info("手动触发泛化规则命中时间更新");
        return updateNormalizeRuleHitTime();
    }

}