use crate::agent::subagent::SubagentSpawnContext;
use crate::session::SessionCommand;
use agent_client_protocol as acp;
use kigi_acp_lib::AcpAgentGatewaySender as GatewaySender;
use kigi_tools::implementations::kigi::task::types::{SubagentRequest, SubagentResult};
use std::collections::HashMap;
use std::path::PathBuf;
use std::sync::Arc;
use tokio::sync::{mpsc, oneshot};
pub(crate) type GatewayOut = <acp::AgentSide as kigi_acp_lib::AcpSide>::OutMessage;
pub(crate) fn test_gateway() -> GatewaySender {
    let (tx, _rx) = mpsc::unbounded_channel();
    GatewaySender::new(tx)
}
/// Like `test_gateway` but returns the receiver; keep it alive for the test.
pub(crate) fn test_gateway_with_receiver() -> (GatewaySender, mpsc::UnboundedReceiver<GatewayOut>) {
    let (tx, rx) = mpsc::unbounded_channel();
    (GatewaySender::new(tx), rx)
}
/// `ctx_with_toggle` with a wired `parent_cmd_tx`.
pub(crate) fn ctx_with_toggle_and_cmd_tx(
    toggle: HashMap<String, bool>,
) -> (
    SubagentSpawnContext,
    mpsc::UnboundedReceiver<SessionCommand>,
) {
    let mut ctx = ctx_with_toggle(toggle);
    let (tx, rx) = mpsc::unbounded_channel();
    ctx.parent_cmd_tx = Some(tx);
    (ctx, rx)
}
pub(crate) fn ctx_with_toggle(toggle: HashMap<String, bool>) -> SubagentSpawnContext {
    let (tx, _rx) = mpsc::unbounded_channel();
    SubagentSpawnContext {
        lsp: None,
        parent_max_turns: None,
        gateway: test_gateway(),
        client_hooks: Default::default(),
        sampling_config: kigi_sampler::SamplerConfig {
            api_key: None,
            base_url: String::new(),
            model: String::new(),
            max_completion_tokens: None,
            temperature: None,
            top_p: None,
            api_backend: Default::default(),
            chat_compat: Default::default(),
            auth_scheme: Default::default(),
            anthropic_oauth: false,
            github_copilot: false,
            openai_codex: false,
            extra_headers: Default::default(),
            context_window: 256_000,
            force_http1: false,
            max_retries: None,
            stream_tool_calls: false,
            idle_timeout_secs: None,
            reasoning_effort: None,
            origin_client: None,
            attribution_callback: None,
            bearer_resolver: None,
            supports_backend_search: false,
            compactions_remaining: None,
            compaction_at_tokens: None,
            doom_loop_recovery: None,
            header_injector: None,
        },
        alpha_test_key: None,
        auth_method_id: acp::AuthMethodId::new("test"),
        model_id: acp::ModelId::new("test"),
        storage_mode: crate::config::StorageMode::Local,
        auth: None,
        parent_cwd: PathBuf::from("/tmp"),
        parent_session_id: "test-parent".into(),
        yolo_mode: false,
        subagent_event_tx: tx,
        hunk_tracker_handle: kigi_hunk_tracker::HunkTrackerHandle::noop(),
        hunk_tracking_enabled: false,
        fs: Arc::new(kigi_workspace::file_system::LocalFs::new(PathBuf::from(
            "/tmp",
        ))),
        terminal: Arc::new(crate::terminal::TerminalRunner::new(
            Arc::new(test_gateway()),
            acp::SessionId::new("test"),
        )),
        session_env: Arc::new(HashMap::new()),
        memory_config: None,
        web_search_config: Default::default(),
        web_fetch_config: Default::default(),
        app_builder_deployer_config: Default::default(),
        write_file_enabled: true,
        goal_enabled: false,
        ask_user_question_enabled: true,
        parent_cmd_tx: None,
        parent_session_info: None,
        subagent_roles: HashMap::new(),
        subagent_personas: HashMap::new(),
        persona_io_summaries: Vec::new(),
        parent_chat_state: None,
        available_models: indexmap::IndexMap::new(),
        subagent_model_overrides: HashMap::new(),
        subagent_toggle: toggle,
        disable_web_search: false,
        todo_gate: false,
        remote_settings: None,
        laziness_debug_log: None,
        backend_tools_enabled: true,
        respect_gitignore: false,
        path_not_found_hints: false,
        plugin_registry: None,
        models_manager: Default::default(),
        file_tool_overrides: None,
        agent_config: None,
        hook_registry: None,
        hook_workspace_root: String::new(),
        parent_depth: 0,
        inference_idle_timeout_secs: 600,
        auto_compact_threshold_tiers: crate::agent::subagent::AutoCompactThresholdTiers::default(),
        permission_handle: None,
        worktree_type: crate::util::config::WorktreeType::Linked,
        api_key_provider: None,
        image_description_model: crate::test_support::TEST_MODEL.to_owned(),
        workspace_ops: kigi_workspace::WorkspaceOps::for_test(),
        auth_manager: Arc::new(crate::auth::AuthManager::new(
            std::path::Path::new("/tmp/nonexistent-kigi-test"),
            crate::auth::KimiCodeConfig::default(),
        )),
        attribution_callback: None,
        parent_agent_name: None,
        parent_model_agent_type: None,
        allowed_subagent_types: None,
        parent_mcp_configs: vec![],
        parent_mcp_pool: None,
        parent_tool_snapshot: None,
        parent_skills: None,
        parent_skills_config: kigi_agent::prompt::skills::SkillsConfig::default(),
        parent_compat: kigi_tools::types::compat::CompatConfig::default(),
        auto_wake_delivered: None,
        task_output_tool_name: kigi_tools::reminders::task_completion::DEFAULT_TASK_OUTPUT_TOOL
            .to_string(),
        auto_wake_enabled: true,
        goal_loop_active: std::sync::Arc::new(std::sync::atomic::AtomicBool::new(false)),
        parent_blocking_wait_depth: std::sync::Arc::new(std::sync::atomic::AtomicUsize::new(0)),
        parent_terminal_backend: None,
        parent_notification_handle: None,
        parent_scheduler_handle: None,
    }
}
pub(crate) fn make_request(
    subagent_type: &str,
) -> (SubagentRequest, oneshot::Receiver<SubagentResult>) {
    let (tx, rx) = oneshot::channel();
    let req = SubagentRequest {
        id: uuid::Uuid::now_v7().to_string(),
        prompt: "do something".into(),
        description: "test task".into(),
        subagent_type: subagent_type.into(),
        parent_session_id: "test-parent".into(),
        parent_prompt_id: Some("parent-prompt".into()),
        resume_from: None,
        cwd: None,
        runtime_overrides: Default::default(),
        run_in_background: false,
        surface_completion: true,
        fork_context: false,
        result_tx: tx,
    };
    (req, rx)
}
#[derive(Default)]
pub(crate) struct DummyLspDispatch;
#[async_trait::async_trait]
impl kigi_tools::implementations::lsp::LspBackend for DummyLspDispatch {
    fn ensure_started_background(&self) {}
    async fn ensure_ready(&self) -> Result<(), String> {
        Ok(())
    }
    fn is_ready(&self) -> bool {
        true
    }
    async fn dispatch(
        &self,
        _input: &kigi_tools::implementations::lsp::LspToolInput,
    ) -> kigi_tools::implementations::lsp::LspToolResult {
        kigi_tools::implementations::lsp::LspToolResult {
            text: String::new(),
            is_error: false,
        }
    }
    async fn drain_diagnostics(
        &self,
        _timeout: std::time::Duration,
    ) -> Option<kigi_tools::implementations::lsp::DiagnosticsSummary> {
        None
    }
    async fn notify_file_changed(&self, _path: &std::path::Path, _content: &str) {}
    async fn read_diagnostics(
        &self,
        _paths: &[std::path::PathBuf],
    ) -> Vec<kigi_tools::implementations::lsp::FileDiagnosticEntry> {
        vec![]
    }
}
