"""
Unit Tests for Preemption Engine
"""

import pytest
import time
from altrus.core.intent.intent import Intent, IntentPriority
from altrus.core.intent.preemption_engine import PreemptionEngine, PreemptionRule

@pytest.fixture
def engine():
    return PreemptionEngine()

def test_default_preemption_rules(engine):
    """Test default rules (High/Critical preempt others)"""
    low_intent = Intent("i1", "low", "cap.a", IntentPriority.LOW)
    normal_intent = Intent("i2", "normal", "cap.a", IntentPriority.NORMAL)
    high_intent = Intent("i3", "high", "cap.a", IntentPriority.HIGH)
    critical_intent = Intent("i4", "critical", "cap.a", IntentPriority.CRITICAL)

    # High should preempt Normal
    assert engine.should_preempt(high_intent, normal_intent) is True

    # Normal should NOT preempt Normal
    assert engine.should_preempt(Intent("i5", "n2", "cap.a", IntentPriority.NORMAL), normal_intent) is False

    # Low should NOT preempt Normal
    assert engine.should_preempt(low_intent, normal_intent) is False

def test_custom_preemption_rule(engine):
    """Test adding custom rules"""
    # Rule: Allow preemption for specific capability even at NORMAL priority
    rule = PreemptionRule(
        name="emergency_nav",
        min_priority=IntentPriority.NORMAL,
        capability_patterns=["nav.emergency"],
        allow_preemption=True
    )
    engine.add_rule(rule)

    normal_nav = Intent("i1", "nav", "nav.emergency", IntentPriority.NORMAL)
    low_task = Intent("i2", "low", "other.cap", IntentPriority.LOW)

    # Matches rule and higher priority than LOW
    assert engine.should_preempt(normal_nav, low_task) is True

def test_deny_preemption_rule(engine):
    """Test rules that explicitly deny preemption"""
    # Rule: Background tasks are FORBIDDEN from preempting, even if they are HIGH priority
    rule = PreemptionRule(
        name="deny_background_preemption",
        min_priority=IntentPriority.LOW,
        capability_patterns=["background.*"],
        allow_preemption=False
    )
    engine.add_rule(rule)

    background_high = Intent("i1", "bg", "background.sync", IntentPriority.HIGH)
    normal_task = Intent("i2", "norm", "task.any", IntentPriority.NORMAL)

    # Matches background rule which denies preemption
    assert engine.should_preempt(background_high, normal_task) is False

def test_preemption_metrics(engine):
    """Test preemption metrics tracking"""
    low = Intent("low", "low", "cap.a", IntentPriority.LOW)
    high = Intent("high", "high", "cap.a", IntentPriority.HIGH)

    engine.should_preempt(high, low)

    metrics = engine.get_metrics()
    assert metrics["total_preemptions"] == 1
    assert metrics["preemptions_by_capability"]["cap.a"] == 1

    history = engine.get_preemption_history()
    assert len(history) == 1
    assert history[0]["new_intent_id"] == "high"
    assert history[0]["preempted_intent_id"] == "low"
