package com.qaup.collision.rule.service;

import com.qaup.collision.common.model.MovingObject.MovingObjectType;
import com.qaup.collision.rule.event.RuleViolationEvent;
import com.qaup.collision.rule.model.entity.SpatialRule;
import com.qaup.collision.rule.model.enums.RuleExecutionResult;
import com.qaup.collision.rule.model.enums.RuleExecutionStatus;

import org.locationtech.jts.geom.Point;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

/**
 * 规则执行引擎接口
 * 负责执行空间规则检查、违规检测和事件生成
 * 
 * @author AI Assistant
 * @version 1.0
 * @since 2025-01-17
 */
public interface RuleExecutionEngine {

    // ========== 核心执行方法 ==========

    /**
     * 执行单个规则检查
     * @param rule 要执行的规则
     * @param vehicleId 车辆ID
     * @param vehicleType 车辆类型
     * @param location 车辆位置
     * @param vehicleState 车辆状态（速度、高度、重量等）
     * @param timestamp 检查时间戳
     * @return 规则执行结果
     */
    RuleExecutionResult executeRule(SpatialRule rule, String vehicleId, MovingObjectType vehicleType,
                                    Point location, Map<String, Object> vehicleState, LocalDateTime timestamp);

    /**
     * 批量执行规则检查
     * @param rules 要执行的规则列表
     * @param vehicleId 车辆ID
     * @param vehicleType 车辆类型
     * @param location 车辆位置
     * @param vehicleState 车辆状态
     * @param timestamp 检查时间戳
     * @return 规则执行结果列表
     */
    List<RuleExecutionResult> executeRules(List<SpatialRule> rules, String vehicleId, MovingObjectType vehicleType,
                                           Point location, Map<String, Object> vehicleState, LocalDateTime timestamp);

    /**
     * 执行位置相关的所有适用规则
     * @param vehicleId 车辆ID
     * @param vehicleType 车辆类型
     * @param location 车辆位置
     * @param vehicleState 车辆状态
     * @param timestamp 检查时间戳
     * @return 规则执行结果列表
     */
    List<RuleExecutionResult> executeLocationRules(String vehicleId, MovingObjectType vehicleType,
                                                    Point location, Map<String, Object> vehicleState, 
                                                    LocalDateTime timestamp);

    // ========== 违规检测方法 ==========

    /**
     * 检测规则违规并生成违规事件
     * @param rule 规则
     * @param vehicleId 车辆ID
     * @param vehicleType 车辆类型
     * @param location 车辆位置
     * @param vehicleState 车辆状态
     * @param timestamp 检查时间戳
     * @return 违规事件，如果没有违规返回null
     */
    RuleViolationEvent detectViolation(SpatialRule rule, String vehicleId, MovingObjectType vehicleType,
                                       Point location, Map<String, Object> vehicleState, LocalDateTime timestamp);

    /**
     * 批量检测违规
     * @param rules 规则列表
     * @param vehicleId 车辆ID
     * @param vehicleType 车辆类型
     * @param location 车辆位置
     * @param vehicleState 车辆状态
     * @param timestamp 检查时间戳
     * @return 违规事件列表
     */
    List<RuleViolationEvent> detectViolations(List<SpatialRule> rules, String vehicleId, MovingObjectType vehicleType,
                                              Point location, Map<String, Object> vehicleState, LocalDateTime timestamp);

    /**
     * 检测所有位置相关的违规
     * @param vehicleId 车辆ID
     * @param vehicleType 车辆类型
     * @param location 车辆位置
     * @param vehicleState 车辆状态
     * @param timestamp 检查时间戳
     * @return 违规事件列表
     */
    List<RuleViolationEvent> detectAllViolations(String vehicleId, MovingObjectType vehicleType,
                                                  Point location, Map<String, Object> vehicleState, 
                                                  LocalDateTime timestamp);

    // ========== 规则适用性检查 ==========

    /**
     * 检查规则是否适用于指定车辆和时间
     * @param rule 规则
     * @param vehicleType 车辆类型
     * @param timestamp 时间戳
     * @return 如果规则适用返回true
     */
    boolean isRuleApplicable(SpatialRule rule, MovingObjectType vehicleType, LocalDateTime timestamp);

    /**
     * 检查车辆是否在规则的空间范围内
     * @param rule 规则
     * @param location 车辆位置
     * @return 如果在范围内返回true
     */
    boolean isLocationInRuleScope(SpatialRule rule, Point location);

    /**
     * 检查当前时间是否在规则的有效时间范围内
     * @param rule 规则
     * @param timestamp 时间戳
     * @return 如果在有效时间内返回true
     */
    boolean isTimeInRuleScope(SpatialRule rule, LocalDateTime timestamp);

    /**
     * 检查车辆类型是否被规则允许
     * @param rule 规则
     * @param vehicleType 车辆类型
     * @return 如果被允许返回true
     */
    boolean isVehicleTypeAllowed(SpatialRule rule, MovingObjectType vehicleType);

    // ========== 规则执行历史 ==========

    /**
     * 记录规则执行历史
     * @param rule 规则
     * @param vehicleId 车辆ID
     * @param vehicleType 车辆类型
     * @param location 车辆位置
     * @param executionStatus 执行状态
     * @param executionResult 执行结果
     * @param timestamp 执行时间
     * @param executionDetails 执行详情
     */
    void recordExecutionHistory(SpatialRule rule, String vehicleId, MovingObjectType vehicleType,
                               Point location, RuleExecutionStatus executionStatus, 
                               RuleExecutionResult executionResult, LocalDateTime timestamp,
                               Map<String, Object> executionDetails);

    /**
     * 获取规则执行历史统计
     * @param ruleId 规则ID
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 执行统计信息
     */
    Map<String, Object> getRuleExecutionStatistics(String ruleId, LocalDateTime startTime, LocalDateTime endTime);

    /**
     * 获取车辆的规则执行历史
     * @param vehicleId 车辆ID
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 执行历史列表
     */
    List<Map<String, Object>> getVehicleExecutionHistory(String vehicleId, LocalDateTime startTime, LocalDateTime endTime);

    // ========== 性能优化方法 ==========

    /**
     * 预加载规则执行所需的数据
     * @param location 位置
     * @param radiusMeters 预加载半径
     */
    void preloadRuleData(Point location, double radiusMeters);

    /**
     * 清理规则执行缓存
     */
    void clearExecutionCache();

    /**
     * 获取规则执行性能指标
     * @return 性能指标Map
     */
    Map<String, Object> getExecutionMetrics();

    // ========== 规则执行上下文 ==========

    /**
     * 规则执行上下文类
     * 封装规则执行的完整信息
     */
    class RuleExecutionContext {
        private final SpatialRule rule;
        private final String vehicleId;
        private final MovingObjectType vehicleType;
        private final Point location;
        private final Map<String, Object> vehicleState;
        private final LocalDateTime timestamp;
        private final RuleExecutionStatus status;
        private final RuleExecutionResult result;
        private final String description;
        private final Map<String, Object> executionDetails;
        private final long executionTimeMs;

        public RuleExecutionContext(SpatialRule rule, String vehicleId, MovingObjectType vehicleType,
                                   Point location, Map<String, Object> vehicleState, LocalDateTime timestamp,
                                   RuleExecutionStatus status, RuleExecutionResult result, String description,
                                   Map<String, Object> executionDetails, long executionTimeMs) {
            this.rule = rule;
            this.vehicleId = vehicleId;
            this.vehicleType = vehicleType;
            this.location = location;
            this.vehicleState = vehicleState;
            this.timestamp = timestamp;
            this.status = status;
            this.result = result;
            this.description = description;
            this.executionDetails = executionDetails;
            this.executionTimeMs = executionTimeMs;
        }

        // Getters
        public SpatialRule getRule() { return rule; }
        public String getVehicleId() { return vehicleId; }
        public MovingObjectType getVehicleType() { return vehicleType; }
        public Point getLocation() { return location; }
        public Map<String, Object> getVehicleState() { return vehicleState; }
        public LocalDateTime getTimestamp() { return timestamp; }
        public RuleExecutionStatus getStatus() { return status; }
        public RuleExecutionResult getResult() { return result; }
        public String getDescription() { return description; }
        public Map<String, Object> getExecutionDetails() { return executionDetails; }
        public long getExecutionTimeMs() { return executionTimeMs; }

        /**
         * 检查是否有违规
         */
        public boolean hasViolation() {
            return result != null && result.isViolation();
        }

        /**
         * 检查执行是否成功
         */
        public boolean isSuccessful() {
            return status == RuleExecutionStatus.SUCCESS;
        }
    }
} 