package com.qaup.collision.rule.event;

import lombok.Getter;
import org.springframework.context.ApplicationEvent;

import java.time.LocalDateTime;
import com.qaup.collision.rule.model.enums.ViolationType;

/**
 * 规则违规事件
 * 当检测到规则违规时发布此事件
 */
@Getter
public class RuleViolationEventOccurred extends ApplicationEvent {

    /**
     * 违规事件详情
     */
    private final RuleViolationEvent violationEvent;

    /**
     * 事件发生时间
     */
    private final LocalDateTime eventTimestamp;

    /**
     * 事件源标识
     */
    private final String eventSource;

    /**
     * 事件优先级
     */
    private final EventPriority priority;

    /**
     * 是否需要立即处理
     */
    private final boolean requiresImmediateAction;

    /**
     * 事件上下文信息
     */
    private final String contextInfo;

    /**
     * 事件优先级枚举
     */
    public enum EventPriority {
        LOW(1, "低优先级"),
        NORMAL(2, "普通优先级"), 
        HIGH(3, "高优先级"),
        CRITICAL(4, "紧急优先级");

        private final int level;
        private final String description;

        EventPriority(int level, String description) {
            this.level = level;
            this.description = description;
        }

        public int getLevel() {
            return level;
        }

        public String getDescription() {
            return description;
        }

        public boolean isHigherThan(EventPriority other) {
            return this.level > other.level;
        }
    }

    /**
     * 构造函数
     *
     * @param source 事件源对象
     * @param violationEvent 违规事件详情
     * @param eventSource 事件源标识
     * @param contextInfo 上下文信息
     */
    public RuleViolationEventOccurred(Object source, RuleViolationEvent violationEvent, 
                                    String eventSource, String contextInfo) {
        super(source);
        this.violationEvent = violationEvent;
        this.eventTimestamp = LocalDateTime.now();
        this.eventSource = eventSource;
        this.contextInfo = contextInfo;
        
        // 根据违规严重程度确定事件优先级
        this.priority = determinePriority(violationEvent);
        this.requiresImmediateAction = determineImmediateAction(violationEvent);
    }

    /**
     * 简化构造函数
     */
    public RuleViolationEventOccurred(Object source, RuleViolationEvent violationEvent) {
        this(source, violationEvent, "RuleEngine", "规则引擎检测到违规");
    }

    /**
     * 根据违规事件确定优先级
     */
    private EventPriority determinePriority(RuleViolationEvent violationEvent) {
        if (violationEvent.getViolationType().equals("CRITICAL")) {
            return EventPriority.CRITICAL;
        } else if (violationEvent.getViolationType().equals("HIGH")) {
            return EventPriority.HIGH;
        } else if (violationEvent.getViolationType().equals("NORMAL")) {
            return EventPriority.NORMAL;
        } else {
            return EventPriority.LOW;
        }
    }

    /**
     * 确定是否需要立即处理
     */
    private boolean determineImmediateAction(RuleViolationEvent violationEvent) {
        // 高严重性或特定违规类型需要立即处理
        return violationEvent.getViolationType().equals("CRITICAL") || 
               isEmergencyViolationType(ViolationType.valueOf(violationEvent.getViolationType()));
    }

    /**
     * 判断是否为紧急违规类型
     */
    private boolean isEmergencyViolationType(ViolationType violationType) {
        switch (violationType) {
            case ACCESS:
            case SAFETY_ZONE:
            case PRIORITY:
                return true;
            default:
                return false;
        }
    }

    /**
     * 获取事件描述
     */
    public String getEventDescription() {
        return String.format("规则违规事件 - 车辆ID: %s, 规则名称: %s, 违规类型: %s, 优先级: %s",
                violationEvent.getVehicleId(),
                violationEvent.getRuleName(),
                violationEvent.getViolationType(),
                priority.name());
    }

    /**
     * 判断是否为高优先级事件
     */
    public boolean isHighPriority() {
        return priority.isHigherThan(EventPriority.NORMAL);
    }

    /**
     * 判断是否为紧急事件
     */
    public boolean isCriticalEvent() {
        return priority == EventPriority.CRITICAL;
    }

    @Override
    public String toString() {
        return String.format("RuleViolationEventOccurred{" +
                "eventId='%s', " +
                "vehicleId='%s', " +
                "ruleName='%s', " +
                "priority=%s, " +
                "timestamp=%s, " +
                "requiresImmediateAction=%s" +
                "}",
                violationEvent.getId(),
                violationEvent.getVehicleId(),
                violationEvent.getRuleName(),
                priority.name(),
                eventTimestamp,
                requiresImmediateAction);
    }
} 