// ABOUTME: CLI entry point for the embacle MCP server binary
// ABOUTME: Parses arguments, selects transport (stdio or HTTP), and starts serving
//
// SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2026 dravr.ai

#![cfg_attr(
    test,
    allow(
        clippy::unwrap_used,
        clippy::expect_used,
        clippy::panic,
        clippy::str_to_string
    )
)]

use std::error::Error;
use std::sync::Arc;

use clap::Parser;
use dravr_tronc::mcp::transport::{http, stdio};
use dravr_tronc::server::cli::McpArgs;
use dravr_tronc::server::tracing_init;
use dravr_tronc::McpServer;
use embacle::types::RunnerError;
use embacle_mcp::runner::{parse_runner_type, valid_provider_names};
use embacle_mcp::ServerState;

/// embacle-mcp — MCP server exposing embacle LLM runners via Model Context Protocol
#[derive(Parser)]
#[command(name = "embacle-mcp", version, about)]
struct Cli {
    #[command(flatten)]
    server: McpArgs,

    /// Default LLM provider
    ///
    /// Valid: claude, copilot, cursor-agent, opencode, gemini, codex, goose, cline, continue, warp, kiro, kilo
    #[arg(long, default_value = "copilot")]
    provider: String,
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
    let cli = Cli::parse();
    tracing_init::init(&cli.server.transport);

    let provider = parse_runner_type(&cli.provider).ok_or_else(|| {
        RunnerError::config(format!(
            "Unknown provider: {}. Valid: {}",
            cli.provider,
            valid_provider_names()
        ))
    })?;

    let state = Arc::new(ServerState::new(provider));
    let registry = embacle_mcp::build_tool_registry();
    let server = Arc::new(McpServer::new(
        "embacle-mcp",
        env!("CARGO_PKG_VERSION"),
        registry,
        state,
    ));

    tracing::info!(
        transport = %cli.server.transport,
        provider = %provider,
        "Starting embacle MCP server"
    );

    match cli.server.transport.as_str() {
        "stdio" => stdio::run(server).await?,
        "http" => {
            http::serve(server, &cli.server.host, cli.server.port).await?;
        }
        other => {
            return Err(RunnerError::config(format!(
                "Unknown transport: {other}. Valid: stdio, http"
            ))
            .into());
        }
    }

    Ok(())
}
