//! Shared infrastructure — creates Runtimes that share state, log, and policies.

use car_engine::Runtime;
use car_eventlog::EventLog;
use car_policy::PolicyEngine;
use car_state::StateStore;
use std::sync::Arc;
use tokio::sync::{Mutex as TokioMutex, RwLock as TokioRwLock};

/// Factory for creating Runtime instances with shared state, event log, and policies.
///
/// In a multi-agent system, all agents see the same state store and write to the
/// same event log. Each agent gets its own tool set and executor.
pub struct SharedInfra {
    pub state: Arc<StateStore>,
    pub log: Arc<TokioMutex<EventLog>>,
    pub policies: Arc<TokioRwLock<PolicyEngine>>,
}

impl SharedInfra {
    pub fn new() -> Self {
        Self {
            state: Arc::new(StateStore::new()),
            log: Arc::new(TokioMutex::new(EventLog::new())),
            policies: Arc::new(TokioRwLock::new(PolicyEngine::new())),
        }
    }

    /// Create a Runtime that shares this infra's state, log, and policies.
    ///
    /// Each runtime gets its own tool set, executor, and idempotency cache.
    pub fn make_runtime(&self) -> Runtime {
        Runtime::with_shared(
            Arc::clone(&self.state),
            Arc::clone(&self.log),
            Arc::clone(&self.policies),
        )
    }

    /// Create a Runtime with per-agent isolated state overlay.
    /// Writes go to a local StateStore; reads fall through to shared state.
    /// Call `AgentContext::merge_to_parent()` after the agent completes.
    pub fn make_isolated_runtime(
        &self,
        agent_name: &str,
    ) -> (Runtime, crate::task_context::AgentContext) {
        let ctx = crate::task_context::AgentContext::new(agent_name, Arc::clone(&self.state));
        let rt = Runtime::with_shared(
            Arc::clone(&ctx.local_state),
            Arc::clone(&ctx.local_log),
            Arc::clone(&self.policies),
        );
        (rt, ctx)
    }
}

impl Default for SharedInfra {
    fn default() -> Self {
        Self::new()
    }
}
