"""
Preemption Engine

Advanced preemption rules for intent arbitration.
"""

from typing import Dict, Optional, List
from dataclasses import dataclass
import time

from altrus.core.intent.intent import Intent, IntentPriority


@dataclass
class PreemptionRule:
    """Defines a preemption rule"""
    name: str
    min_priority: IntentPriority
    capability_patterns: List[str]  # Glob patterns for capabilities
    allow_preemption: bool = True

    def matches(self, intent: Intent) -> bool:
        """Check if this rule applies to the intent"""
        # Check priority
        if intent.priority.value > self.min_priority.value:
            return False

        # Check capability patterns
        if not self.capability_patterns:
            return True

        for pattern in self.capability_patterns:
            if self._matches_pattern(intent.capability, pattern):
                return True

        return False

    def _matches_pattern(self, capability: str, pattern: str) -> bool:
        """Simple glob pattern matching"""
        if pattern == "*":
            return True
        if pattern.endswith(".*"):
            prefix = pattern[:-2]
            return capability.startswith(prefix)
        return capability == pattern


class PreemptionEngine:
    """
    Advanced preemption engine with configurable rules.

    Features:
    - Priority-based preemption
    - Capability-specific rules
    - Preemption analytics
    - Configurable thresholds
    """

    def __init__(self, config: Optional[Dict] = None):
        self._config = config or {}
        self._rules: List[PreemptionRule] = []

        # Default rule: allow preemption for HIGH and CRITICAL
        self._rules.append(
            PreemptionRule(
                name="default_high_priority",
                min_priority=IntentPriority.HIGH,
                capability_patterns=["*"],
                allow_preemption=True
            )
        )

        # Metrics
        self._total_preemptions = 0
        self._preemptions_by_capability: Dict[str, int] = {}
        self._preemption_history: List[Dict] = []

    def add_rule(self, rule: PreemptionRule):
        """Add a preemption rule (inserted at the beginning for high priority)"""
        self._rules.insert(0, rule)

    def should_preempt(
        self,
        new_intent: Intent,
        current_intent: Optional[Intent]
    ) -> bool:
        """
        Determine if new intent should preempt current intent.

        Args:
            new_intent: Incoming intent
            current_intent: Currently executing intent (None if no intent executing)

        Returns:
            True if new intent should preempt, False otherwise
        """
        # If nothing executing, no preemption needed
        if current_intent is None:
            return True

        # Check if new intent has higher priority
        if new_intent.priority.value >= current_intent.priority.value:
            return False

        # Check preemption rules
        for rule in self._rules:
            if rule.matches(new_intent):
                if rule.allow_preemption:
                    self._record_preemption(new_intent, current_intent)
                    return True
                else:
                    return False

        # No matching rule, default to no preemption
        return False

    def _record_preemption(self, new_intent: Intent, preempted_intent: Intent):
        """Record preemption for analytics"""
        self._total_preemptions += 1

        capability = new_intent.capability
        self._preemptions_by_capability[capability] = \
            self._preemptions_by_capability.get(capability, 0) + 1

        self._preemption_history.append({
            "timestamp": time.time(),
            "new_intent_id": new_intent.intent_id,
            "new_priority": new_intent.priority.value,
            "preempted_intent_id": preempted_intent.intent_id,
            "preempted_priority": preempted_intent.priority.value,
            "capability": new_intent.capability
        })

        # Keep only last 100 preemptions
        if len(self._preemption_history) > 100:
            self._preemption_history.pop(0)

    def get_metrics(self) -> dict:
        """Get preemption analytics"""
        return {
            "total_preemptions": self._total_preemptions,
            "preemptions_by_capability": self._preemptions_by_capability.copy(),
            "recent_preemptions": len(self._preemption_history),
            "rules_count": len(self._rules)
        }

    def get_preemption_history(self, limit: int = 10) -> List[Dict]:
        """Get recent preemption history"""
        return self._preemption_history[-limit:]
