//! Connector Summary Cache
//!
//! This module manages a synchronous cache of connector summary information
//! that can be accessed from callbacks without an async runtime.

use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::RwLock;
use tracing::warn;

use crate::config::CoreConfig;
use crate::connectors::gateway::ConnectorSummaryInfo;
use crate::connectors::{Connector, ConnectorHandle};
use crate::types::ConnectorKind;

/// Update the connector summary cache from the current connectors map
///
/// This function rebuilds the sync-accessible cache used by GatewayConnector
/// callbacks. It should be called after any connector is added or removed.
///
/// The cache uses a std::sync::RwLock so it can be accessed from synchronous
/// callback functions that don't have access to an async runtime.
///
/// # Arguments
///
/// * `connectors` - Read-locked map of connector handles
/// * `config` - Read-locked runtime configuration
/// * `cache` - The std::sync::RwLock cache to update
pub async fn update_connector_summary_cache(
    connectors: &RwLock<HashMap<String, ConnectorHandle>>,
    config: &RwLock<CoreConfig>,
    cache: &Arc<std::sync::RwLock<Vec<ConnectorSummaryInfo>>>,
) {
    let connectors_guard = connectors.read().await;
    let config_guard = config.read().await;

    let summaries: Vec<ConnectorSummaryInfo> = connectors_guard
        .values()
        .map(|handle| {
            let kind = handle.kind();
            let connector_id = handle.id();

            // Get agent_type for ACP connectors
            let agent_type = if kind == ConnectorKind::Acp {
                config_guard
                    .connectors
                    .iter()
                    .find(|c| c.id.as_deref() == Some(connector_id))
                    .and_then(|cfg| {
                        serde_json::from_value::<crate::connectors::acp::config::AcpConfig>(
                            cfg.params.clone(),
                        )
                        .ok()
                    })
                    .map(|cfg| cfg.agent_type)
            } else {
                None
            };

            ConnectorSummaryInfo {
                id: connector_id.to_string(),
                title: handle.title().to_string(),
                kind: format!("{:?}", kind),
                state: format!("{:?}", handle.state()),
                supports_session_transfer: kind.supports_session_transfer(),
                agent_type,
            }
        })
        .collect();

    // Update the sync cache (this lock should never block for long since we're just writing a Vec)
    if let Ok(mut cache_guard) = cache.write() {
        *cache_guard = summaries;
    } else {
        warn!("Failed to acquire connector summary cache lock for update");
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::config::CoreConfig;
    use std::sync::Arc;

    #[tokio::test]
    async fn test_update_empty_cache() {
        let connectors = RwLock::new(HashMap::new());
        let config = RwLock::new(CoreConfig::default());
        let cache = Arc::new(std::sync::RwLock::new(Vec::new()));

        update_connector_summary_cache(&connectors, &config, &cache).await;

        let cached = cache.read().unwrap();
        assert!(cached.is_empty());
    }
}
