//! Channel factory for routing providers to transport adapters.

use std::sync::Arc;

use crate::agent;
use crate::app_server::AppServerClient;
use crate::channel::app_server::AppServerAgentChannel;
use crate::channel::cli::CliAgentChannel;
use crate::channel::contract::AgentChannel;
use crate::model::agent::AgentKind;

/// Creates the provider-specific channel for the given agent kind.
///
/// CLI providers (Antigravity, Claude) use [`CliAgentChannel`];
/// app-server providers (Gemini, Codex) use [`AppServerAgentChannel`].
pub fn create_agent_channel(
    kind: AgentKind,
    app_server_client_override: Option<Arc<dyn AppServerClient>>,
) -> Arc<dyn AgentChannel> {
    let backend = agent::create_backend(kind);
    let transport = agent::transport_mode(kind);

    if transport.uses_app_server() {
        match agent::create_app_server_client(kind, app_server_client_override) {
            Some(app_server_client) => {
                Arc::new(AppServerAgentChannel::new(app_server_client, kind))
            }
            None => Arc::new(CliAgentChannel::with_backend(Arc::from(backend), kind)),
        }
    } else {
        Arc::new(CliAgentChannel::with_backend(Arc::from(backend), kind))
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn create_agent_channel_returns_cli_channel_for_claude() {
        // Arrange / Act
        let channel = create_agent_channel(AgentKind::Claude, None);

        // Assert
        assert_eq!(Arc::strong_count(&channel), 1);
    }

    #[test]
    fn create_agent_channel_returns_cli_channel_for_antigravity() {
        // Arrange / Act
        let channel = create_agent_channel(AgentKind::Antigravity, None);

        // Assert
        assert_eq!(Arc::strong_count(&channel), 1);
    }

    #[test]
    fn create_agent_channel_returns_app_server_channel_for_codex() {
        // Arrange / Act
        let channel = create_agent_channel(AgentKind::Codex, None);

        // Assert
        assert_eq!(Arc::strong_count(&channel), 1);
    }

    #[test]
    fn create_agent_channel_returns_app_server_channel_for_gemini() {
        // Arrange / Act
        let channel = create_agent_channel(AgentKind::Gemini, None);

        // Assert
        assert_eq!(Arc::strong_count(&channel), 1);
    }
}
