"""
Auditor's Evidence Suite for ALTRUS Compliance.
Provides concrete proof for Intent Lifecycle, Fault Escalation, and Ledger Integrity.
"""

import pytest
import time
import json
import os
from pathlib import Path
from altrus.core.kernel import AltrusKernel
from altrus.core.intent.intent import Intent, IntentState, IntentPriority
from altrus.core.lifecycle import SystemState
from altrus.core.fault.state_machine import FaultSeverity
from altrus.core.ledger.verifier import LedgerVerifier
from altrus.core.registry.module import Module, ModuleState

def test_intent_lifecycle_compliance(tmp_path):
    """PROVES: PENDING -> SCHEDULED -> EXECUTING -> COMPLETED lifecycle."""
    # Use different ports to avoid conflicts
    os.environ["ALTRUS_METRICS_PORT"] = "9000"
    os.environ["ALTRUS_BRIDGE_PORT"] = "9001"

    kernel = AltrusKernel(storage_dir=tmp_path)

    # 1. PENDING (Created)
    intent = Intent("audit_01", "Audit Task", "sys.audit", priority=IntentPriority.NORMAL)
    assert intent.state == IntentState.PENDING

    # 2. SCHEDULED (Submitted)
    kernel.intent_engine.submit_intent(intent)
    assert intent.state == IntentState.SCHEDULED

    # 3. EXECUTING
    module = Module(
        module_id="auditor_01",
        name="auditor",
        version="1.0.0",
        capabilities=["sys.audit"]
    )
    kernel.registry.register(module)
    kernel.registry.activate("auditor_01")

    kernel.intent_engine.execute_pending_intents()
    assert kernel.intent_engine.current_intent is not None
    assert kernel.intent_engine.current_intent.intent_id == "audit_01"
    assert kernel.intent_engine.current_intent.state == IntentState.EXECUTING

    # 4. COMPLETED
    kernel.intent_engine.mark_intent_completed("audit_01")
    assert intent.state == IntentState.COMPLETED

    # Verify Ledger Logging
    ledger_events = [b.data["event_type"] for b in kernel.ledger.get_chain()]
    assert "INTENT_SUBMITTED" in ledger_events
    assert "INTENT_EXECUTING" in ledger_events
    assert "INTENT_COMPLETED" in ledger_events

    kernel.shutdown()

def test_fault_severity_escalation_compliance(tmp_path):
    """PROVES: SOFT -> HARD escalation on repeated failure."""
    os.environ["ALTRUS_METRICS_PORT"] = "9002"
    os.environ["ALTRUS_BRIDGE_PORT"] = "9003"

    kernel = AltrusKernel(storage_dir=tmp_path)

    # Mock a fault detection
    from altrus.core.fault.detectors import FaultDetector
    class MockDetector(FaultDetector):
        def check(self): return True
        def severity(self): return FaultSeverity.SOFT
        def __str__(self): return "MockSoftFault"

    kernel.fault_engine.detectors = [MockDetector()]

    # Cycle 1: SOFT (First detection)
    kernel.fault_engine.evaluate()

    # Cycle 2: Escalated to HARD
    kernel.fault_engine.evaluate()

    # Ledger/History should reflect ESCALATION
    history = kernel.fault_engine.fault_history
    assert any(h["fault_type"] == "ESCALATION" and h["severity"] == "HARD" for h in history)

    kernel.shutdown()

def test_ledger_tamper_detection(tmp_path):
    """PROVES: Blockchain tamper detection via re-hashing."""
    os.environ["ALTRUS_METRICS_PORT"] = "9004"
    os.environ["ALTRUS_BRIDGE_PORT"] = "9005"

    kernel = AltrusKernel(storage_dir=tmp_path)
    kernel.ledger.log_event("TEST_EVENT", "AUDITOR", "01", {"msg": "Original"})

    # Verify valid
    assert LedgerVerifier.verify(kernel.ledger) is True

    ledger_file = tmp_path / "ledger.json"
    with open(ledger_file, "r") as f:
        data = json.load(f)

    data[1]["data"]["msg"] = "TAMPERED"
    with open(ledger_file, "w") as f:
        json.dump(data, f)

    from altrus.core.ledger.blockchain import BlockchainLedger
    new_ledger = BlockchainLedger(storage_dir=tmp_path)
    assert LedgerVerifier.verify(new_ledger) is False

    kernel.shutdown()

def test_fault_full_escalation_behavior(tmp_path):
    """PROVES: SOFT -> HARD (DEGRADED) -> CRITICAL (FAILED) behavior and normalization."""
    os.environ["ALTRUS_METRICS_PORT"] = "9006"
    os.environ["ALTRUS_BRIDGE_PORT"] = "9007"

    kernel = AltrusKernel(storage_dir=tmp_path)

    # ✅ FIX: Register the module first
    module = Module(
        module_id="mod_1",
        name="test_module",
        version="1.0.0",
        capabilities=["test"]
    )
    kernel.registry.register(module)
    kernel.registry.activate("mod_1")

    kernel.start()
    assert kernel.state_machine.current_state == SystemState.RUNNING

    # 1. SOFT
    kernel.fault_engine.handle_fault("mod_1", "G_SOFT")
    # count=1, eff=SOFT
    assert kernel.state_machine.current_state == SystemState.RUNNING

    # 2. HARD -> DEGRADED
    kernel.fault_engine.handle_fault("mod_1", "G_SOFT")
    # count=2, eff=HARD
    assert kernel.state_machine.current_state == SystemState.DEGRADED

    # 3. CRITICAL -> FAILED
    kernel.fault_engine.handle_fault("mod_1", "G_SOFT")
    # count=3, eff=CRITICAL
    assert kernel.state_machine.current_state == SystemState.FAILED

    # 4. NORMALIZATION
    # Fix detectors (if any)
    kernel.fault_engine.detectors = []
    kernel.fault_engine.reset_recovery()
    assert kernel.state_machine.current_state == SystemState.RUNNING
    assert len(kernel.fault_engine._module_failure_counts) == 0

    kernel.shutdown()
