from pathlib import Path
from typing import Optional, List, Dict

from altrus.core.registry.registry import ModuleRegistry
from altrus.core.intent.intent_engine import IntentEngine
from altrus.core.fault.fault_engine import FaultEngine
from altrus.core.fault.recovery import RestartModuleStrategy
from altrus.core.fault.detectors import HeartbeatDetector
from altrus.core.ledger.blockchain import BlockchainLedger
from altrus.core.registry.health_monitor import HealthMonitor
from altrus.core.observability.server import start_metrics_server
from altrus.core.intent.registry import IntentDefinitionRegistry
from altrus.core.lifecycle import SystemStateMachine, SystemState, StateTransition

from altrus.core.intent.policies.default_policy import DefaultRoutingPolicy
from altrus.core.intent.policies.config_loader import PolicyConfigLoader

from altrus.core.config import ConfigManager
from altrus.core.bridge.adapter import AgnosticBridge

class AltrusKernel:
    """
    Middleware kernel responsible for wiring all core subsystems.

    Manages system lifecycle through state machine:
    INIT -> READY -> RUNNING -> [DEGRADED] -> FAILED
    """

    def __init__(self, storage_dir: Optional[Path] = None, config_path: Optional[Path] = None):
        """
        Args:
            storage_dir: Base directory for all persistent storage. Overrides config if provided.
            config_path: Path to YAML configuration file.
        """
        self._config_manager = ConfigManager(config_path=config_path)
        self.config = self._config_manager.config

        # Override storage dir if provided
        if storage_dir:
            self.config.storage_dir = Path(storage_dir)

        self.storage_dir = self.config.storage_dir
        self.storage_dir.mkdir(parents=True, exist_ok=True)

        # -----------------------------
        # Lifecycle State Machine
        # -----------------------------
        self.state_machine = SystemStateMachine(initial_state=SystemState.INIT)

        # -----------------------------
        # Observability
        # -----------------------------
        self.metrics_server = start_metrics_server(self.config.metrics_port)

        # -----------------------------
        # Load Policy Config
        # -----------------------------
        BASE_DIR = Path(__file__).resolve().parent

        policy_path = (
            BASE_DIR
            / "intent"
            / "policies"
            / "intent_routing.yaml"
        )
        policy_config = PolicyConfigLoader.load(policy_path)

        routing_policy = DefaultRoutingPolicy(
            config=policy_config.get("routing", {})
        )

        preemption_config = policy_config.get("preemption", {})

        # -----------------------------
        # Ledger (audit backbone)
        # -----------------------------
        self.ledger = BlockchainLedger(storage_dir=self.storage_dir)

        # Register state transition callback to log to ledger
        self.state_machine.register_callback(self._log_state_transition)

        # -----------------------------
        # Registry (system truth)
        # -----------------------------
        self.registry = ModuleRegistry(ledger=self.ledger, storage_dir=self.storage_dir)

        # -----------------------------
        # Intent Engine
        # -----------------------------
        self.intent_engine = IntentEngine(
            registry=self.registry,
            ledger=self.ledger,
            policy=routing_policy,
            preemption_config=preemption_config,
            storage_dir=self.storage_dir
        )
        self.registry._intent_engine = self.intent_engine


        # -----------------------------
        # Fault Engine
        # -----------------------------
        heartbeat_detector = HeartbeatDetector()

        self.fault_engine = FaultEngine(
            registry=self.registry,
            intent_engine=self.intent_engine,
            detectors=[heartbeat_detector],
            recovery_strategy=RestartModuleStrategy(),
            state_machine=self.state_machine,
        )


        # -----------------------------
        # Health Monitoring
        # -----------------------------
        self.health_monitor = HealthMonitor(self.registry, fault_engine=self.fault_engine)
        self.health_monitor.start()

        # -----------------------------
        # Agnostic Bridge (Cross-language)
        # -----------------------------
        self.bridge = AgnosticBridge(self, port=self.config.bridge_port)
        self.bridge.start()

        # -----------------------------
        # Intent Definitions
        # -----------------------------
        self.intent_definitions = IntentDefinitionRegistry(
            path=Path("intents.yaml")
        )

        # -----------------------------
        # Transition to READY state
        # -----------------------------
        self.state_machine.transition(
            SystemState.READY,
            reason="Kernel initialization complete"
        )

    def _log_state_transition(self, transition: StateTransition):
        """Log state transitions to blockchain ledger"""
        self.ledger.log_event(
            event_type="SYSTEM_STATE_TRANSITION",
            actor_type="KERNEL",
            actor_id="altrus_kernel",
            data={
                "from_state": transition.from_state.value,
                "to_state": transition.to_state.value,
                "reason": transition.reason,
                "timestamp": transition.timestamp,
                "metadata": transition.metadata or {}
            }
        )

    def start(self) -> None:
        """
        Start the kernel and transition to RUNNING state.

        This triggers the execution of any pending intents and starts the
        health monitoring loop.

        Raises:
            RuntimeError: If kernel is not in READY state.
        """
        if self.state_machine.current_state != SystemState.READY:
            raise RuntimeError(
                f"Cannot start kernel from state {self.state_machine.current_state.value}"
            )

        self.state_machine.transition(
            SystemState.RUNNING,
            reason="Kernel started by user"
        )

        # Start executing pending intents
        self.intent_engine.execute_pending_intents()

    def get_system_state(self) -> SystemState:
        """
        Return the current authoritative state of the ALTRUS system.

        Returns:
            SystemState: Current lifecycle state (e.g., RUNNING, DEGRADED).
        """
        return self.state_machine.current_state

    def shutdown(self, reason: str = "User requested shutdown") -> None:
        """
        Gracefully shutdown the kernel and all managed subsystems.

        This stops health monitoring, logs the shutdown event to the ledger,
        and transitions the system to the FAILED (stopped) state.

        Args:
            reason: Human-readable explanation for the shutdown.
        """
        current_state = self.state_machine.current_state

        # Stop health monitoring
        if hasattr(self.health_monitor, 'stop'):
            self.health_monitor.stop()

        # Stop Agnostic Bridge
        if hasattr(self, 'bridge'):
            self.bridge.stop()

        # Log shutdown
        self.ledger.log_event(
            event_type="KERNEL_SHUTDOWN",
            actor_type="KERNEL",
            actor_id="altrus_kernel",
            data={
                "from_state": current_state.value,
                "reason": reason
            }
        )

        # Transition to FAILED state (represents stopped/shutdown)
        if current_state != SystemState.FAILED:
            self.state_machine.transition(
                SystemState.FAILED,
                reason=reason
            )
