package com.example.demo.service;

import com.example.demo.model.Event;
import com.example.demo.model.dto.EventDTO;
import com.example.demo.model.dto.EventQueryDTO;
import com.example.demo.model.enums.EventStatus;
import com.example.demo.repository.EventRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 事件处理服务。
 * <p>
 * 实现事件的接收、清洗、标准化、存储与状态管理等核心业务逻辑。
 * </p>
 *
 * @requirement(name="事件接收与解析", id="SRS-EHTG-01")
 * 监听上游消息队列，接收原始事件数据包并进行格式校验。
 *
 * @requirement(name="数据清洗与标准化", id="SRS-EHTG-02")
 * 对原始事件进行去重、过滤、字段补全和结构化转换。
 *
 * @requirement(name="事件存储与状态管理", id="SRS-EHTG-03")
 * 将处理后的事件存入数据库，并维护其生命周期状态。
 *
 * @requirement(name="高价值目标评估", id="SRS-EHTG-05")
 * 基于威胁等级、置信度等指标计算目标价值，判定是否触发任务生成。
 */
@Service
public class EventService {

    private static final Logger log = LoggerFactory.getLogger(EventService.class);

    private final EventRepository eventRepository;

    public EventService(EventRepository eventRepository) {
        this.eventRepository = eventRepository;
    }

    /**
     * 接收并处理原始事件。
     * <p>
     * 执行数据清洗与标准化流程：
     * 1. 格式校验
     * 2. 字段补全
     * 3. 去重检查
     * 4. 结构化转换并存储
     * </p>
     *
     * @param rawEvent 原始事件数据
     * @return 处理后的事件
     */
    public Event receiveEvent(Event rawEvent) {
        log.info("接收到原始事件，来源: {}, 时间: {}", rawEvent.getSourceType(), rawEvent.getOccurTime());

        // 格式校验：置信度必须在0~1之间
        if (rawEvent.getConfidence() < 0 || rawEvent.getConfidence() > 1) {
            log.warn("事件置信度异常: {}, 已自动修正", rawEvent.getConfidence());
            rawEvent.setConfidence(Math.max(0, Math.min(1, rawEvent.getConfidence())));
        }

        // 字段补全：如果状态为空，默认设置为待处理
        if (rawEvent.getStatus() == null) {
            rawEvent.setStatus(EventStatus.PENDING);
        }

        // 去重检查（按事件ID）
        if (rawEvent.getEventId() != null && !rawEvent.getEventId().isEmpty()) {
            Optional<Event> existing = eventRepository.findById(rawEvent.getEventId());
            if (existing.isPresent()) {
                log.info("事件 {} 已存在，跳过重复接收", rawEvent.getEventId());
                return existing.get();
            }
        }

        // 结构化转换并存储
        Event savedEvent = eventRepository.save(rawEvent);
        log.info("事件 {} 已清洗并存储", savedEvent.getEventId());

        return savedEvent;
    }

    /**
     * 评估目标价值。
     * <p>
     * 基于威胁等级和置信度计算目标价值评分。
     * 评分公式：威胁等级值 × 置信度 × 100
     * 评分 > 200 视为高价值目标。
     * </p>
     *
     * @param event 事件
     * @return 目标价值评分（0~400）
     */
    public double evaluateTargetValue(Event event) {
        double threatScore = event.getThreatLevel() != null ? event.getThreatLevel().getLevel() : 1;
        double confidence = event.getConfidence();
        double score = threatScore * confidence * 100;
        log.info("事件 {} 目标价值评估: 威胁={}, 置信度={}, 评分={}",
                event.getEventId(), threatScore, confidence, score);
        return score;
    }

    /**
     * 判断是否为高价值目标（评分 > 200）。
     *
     * @param score 目标价值评分
     * @return true 如果是高价值目标
     */
    public boolean isHighValueTarget(double score) {
        return score > 200;
    }

    /**
     * 查询事件列表，支持排序和过滤。
     *
     * @param query 查询参数
     * @return 事件列表
     */
    public List<Event> queryEvents(EventQueryDTO query) {
        List<Event> events = new ArrayList<>(eventRepository.findAll());

        // 状态过滤
        if (query.getStatusFilter() != null && !query.getStatusFilter().isEmpty()) {
            events = events.stream()
                    .filter(e -> e.getStatus() != null &&
                            e.getStatus().getDescription().contains(query.getStatusFilter()))
                    .collect(Collectors.toList());
        }

        // 威胁等级过滤
        if (query.getThreatLevel() != null) {
            events = events.stream()
                    .filter(e -> e.getThreatLevel() == query.getThreatLevel())
                    .collect(Collectors.toList());
        }

        // 排序
        String sortField = query.getSortField();
        String sortDir = query.getSortDirection();
        if (sortField != null && !sortField.isEmpty()) {
            Comparator<Event> comparator = getComparator(sortField);
            if (comparator != null) {
                if ("desc".equalsIgnoreCase(sortDir)) {
                    events.sort(comparator.reversed());
                } else {
                    events.sort(comparator);
                }
            }
        }

        // 分页
        int page = Math.max(0, query.getPage());
        int size = Math.max(1, Math.min(100, query.getSize() > 0 ? query.getSize() : 20));
        int fromIndex = page * size;
        if (fromIndex >= events.size()) {
            return new ArrayList<>();
        }
        int toIndex = Math.min(fromIndex + size, events.size());
        return events.subList(fromIndex, toIndex);
    }

    /**
     * 获取排序比较器。
     */
    private Comparator<Event> getComparator(String sortField) {
        return switch (sortField) {
            case "createTime" -> Comparator.comparing(Event::getCreateTime, Comparator.nullsLast(Comparator.naturalOrder()));
            case "occurTime" -> Comparator.comparing(Event::getOccurTime, Comparator.nullsLast(Comparator.naturalOrder()));
            case "threatLevel" -> Comparator.comparing(e -> e.getThreatLevel() != null ? e.getThreatLevel().getLevel() : 0);
            case "confidence" -> Comparator.comparing(Event::getConfidence);
            default -> null;
        };
    }

    /**
     * 根据ID查询事件。
     *
     * @param eventId 事件ID
     * @return 事件
     */
    public Optional<Event> getEventById(String eventId) {
        return eventRepository.findById(eventId);
    }

    /**
     * 更新事件状态。
     *
     * @param eventId 事件ID
     * @param status  新状态
     * @return 更新后的事件
     */
    public Optional<Event> updateEventStatus(String eventId, EventStatus status) {
        log.info("更新事件 {} 状态为 {}", eventId, status);
        return eventRepository.updateStatus(eventId, status);
    }
}
