"""
Integration Tests

End-to-end integration tests for ALTRUS system.
"""

import pytest
import time
from typing import Optional
from pathlib import Path
from altrus.core.kernel import AltrusKernel
from altrus.core.registry.module import Module
from altrus.core.intent.intent import Intent, IntentPriority
from altrus.core.lifecycle import SystemState


from altrus.core.observability.server import stop_metrics_server


@pytest.mark.integration
class TestFullPipeline:
    """Integration tests for full system pipeline"""

    @pytest.fixture(autouse=True)
    def setup_teardown(self):
        # Stop any residual metrics servers before each test
        stop_metrics_server()
        yield
        # Stop after each test
        stop_metrics_server()

    def test_kernel_initialization(self, tmp_path):
        """Test that kernel initializes all subsystems"""
        kernel = AltrusKernel(storage_dir=tmp_path)

        assert kernel.registry is not None
        assert kernel.intent_engine is not None
        assert kernel.fault_engine is not None
        assert kernel.ledger is not None
        assert kernel.state_machine is not None

    def test_module_registration_and_intent_flow(self, tmp_path):
        """Test complete flow: module registration → intent submission → execution"""
        kernel = AltrusKernel(storage_dir=tmp_path)

        # Register module
        module = Module(
            module_id="test_module",
            name="Test Module",
            version="1.0",
            capabilities=["test.action"]
        )
        kernel.registry.register(module)

        # Start kernel
        kernel.start()
        assert kernel.get_system_state() == SystemState.RUNNING

        # Submit intent
        intent = Intent(
            intent_id="intent_001",
            name="test_intent",
            capability="test.action",
            priority=IntentPriority.NORMAL
        )
        kernel.intent_engine.submit_intent(intent)

        # Verify intent was logged to ledger
        time.sleep(0.1)
        chain = kernel.ledger.get_chain()
        intent_events = [
            b for b in chain
            if "INTENT" in b.data.get("event_type", "")
        ]
        assert len(intent_events) > 0

        kernel.shutdown()

    def test_fault_detection_and_ledger_logging(self, tmp_path):
        """Test fault detection → recovery → ledger logging"""
        kernel = AltrusKernel(storage_dir=tmp_path)

        module = Module("faulty_module", "Faulty", "1.0", ["test.cap"])
        kernel.registry.register(module)

        kernel.start()

        # Simulate fault
        kernel.fault_engine.handle_fault(
            module_id="faulty_module",
            fault_type="TEST_FAULT",
            metadata={"reason": "test"}
        )

        # Check ledger
        time.sleep(0.1)
        chain = kernel.ledger.get_chain()
        fault_events = [
            b for b in chain
            if "FAULT" in b.data.get("event_type", "")
        ]
        assert len(fault_events) > 0

        kernel.shutdown()

    def test_concurrent_intent_handling(self, tmp_path):
        """Test handling multiple concurrent intents"""
        kernel = AltrusKernel(storage_dir=tmp_path)

        # Register multiple modules
        for i in range(3):
            module = Module(
                f"module_{i}",
                f"Module {i}",
                "1.0",
                [f"capability_{i}"]
            )
            kernel.registry.register(module)

        kernel.start()

        # Submit multiple intents
        intents = []
        for i in range(5):
            intent = Intent(
                f"intent_{i}",
                f"name_{i}",
                f"capability_{i % 3}",
                IntentPriority.NORMAL
            )
            kernel.intent_engine.submit_intent(intent)
            intents.append(intent)

        time.sleep(0.5)

        # Verify all intents were processed
        all_intents = kernel.intent_engine.list_intents()
        assert len(all_intents) >= 5

        kernel.shutdown()

    def test_system_degradation_scenario(self, tmp_path):
        """Test system behavior during degradation"""
        kernel = AltrusKernel(storage_dir=tmp_path)

        kernel.start()
        assert kernel.get_system_state() == SystemState.RUNNING

        # Simulate degradation
        kernel.state_machine.transition(
            SystemState.DEGRADED,
            "Simulated partial failure"
        )

        assert kernel.get_system_state() == SystemState.DEGRADED

        # System should still be operational
        assert kernel.registry is not None

        kernel.shutdown()

    def test_blockchain_integrity_after_operations(self, tmp_path):
        """Test blockchain maintains integrity after various operations"""
        kernel = AltrusKernel(storage_dir=tmp_path)
        kernel.start()

        # Perform various operations
        module = Module("m1", "Module 1", "1.0", ["cap1"])
        kernel.registry.register(module)

        intent = Intent("i1", "task1", "cap1", IntentPriority.HIGH)
        kernel.intent_engine.submit_intent(intent)

        kernel.fault_engine.handle_fault("m1", "TEST_FAULT", {})

        time.sleep(0.2)

        # Verify blockchain
        is_valid = kernel.ledger.verify_integrity()
        assert is_valid is True

        kernel.shutdown()


if __name__ == "__main__":
    pytest.main([__file__, "-v", "-m", "integration"])
