//! Dual-channel tool execution helpers.

use anyhow::Result;
use serde_json::Value;
use tracing::{debug, warn};

use crate::config::constants::tools;
use crate::tools::summarizers::{
    Summarizer,
    execution::BashSummarizer,
    file_ops::{EditSummarizer, ReadSummarizer},
    search::{GrepSummarizer, ListSummarizer},
};
use crate::tools::tool_intent;

use super::{SplitToolResult, ToolRegistry};

impl ToolRegistry {
    /// Execute tool with dual-channel output (Phase 4: Split Tool Results).
    ///
    /// This method enables significant token savings by separating:
    /// - `llm_content`: Concise summary sent to LLM context (token-optimized)
    /// - `ui_content`: Rich output displayed to user (full details)
    ///
    /// For tools with registered summarizers, this can achieve 90-97% token reduction
    /// on tool outputs while preserving full details for the UI.
    ///
    /// # Example
    /// ```rust,no_run
    /// let result = registry.execute_tool_dual("grep_file", args).await?;
    /// // result.llm_content: "Found 127 matches in 15 files. Key: src/tools/grep.rs (3)"
    /// // result.ui_content: [Full formatted output with all 127 matches]
    /// // Savings: ~98% token reduction
    /// ```
    pub async fn execute_tool_dual(&self, name: &str, args: Value) -> Result<SplitToolResult> {
        // Execute the tool using existing infrastructure
        let result = self.execute_tool_ref(name, &args).await?;

        // Convert Value to string for UI content
        let ui_content = if result.is_string() {
            result.as_str().unwrap_or("").to_string()
        } else {
            serde_json::to_string_pretty(&result).unwrap_or_else(|_| result.to_string())
        };

        // Get canonical tool name for summarizer lookup
        // Resolve alias through registration lookup first
        let tool_name = if let Some(registration) = self.inventory.registration_for(name) {
            registration.name().to_string()
        } else {
            name.to_string() // Fallback to original name if not found
        };

        // Check if we have a summarizer for this tool
        match tool_name.as_str() {
            tools::UNIFIED_SEARCH => {
                match tool_intent::unified_search_action(&args).unwrap_or("grep") {
                    "grep" => {
                        let summarizer = GrepSummarizer::default();
                        match summarizer.summarize(&ui_content, None) {
                            Ok(llm_content) => {
                                debug!(
                                    tool = tools::UNIFIED_SEARCH,
                                    action = "grep",
                                    ui_tokens = %summarizer.estimate_savings(&ui_content, &llm_content).1,
                                    llm_tokens = %summarizer.estimate_savings(&ui_content, &llm_content).0,
                                    savings_pct = %summarizer.estimate_savings(&ui_content, &llm_content).2,
                                    "Applied grep summarization"
                                );
                                Ok(SplitToolResult::new(
                                    tool_name.as_str(),
                                    llm_content,
                                    ui_content,
                                ))
                            }
                            Err(e) => {
                                warn!(
                                    tool = tools::UNIFIED_SEARCH,
                                    action = "grep",
                                    error = %e,
                                    "Failed to summarize grep output, using simple result"
                                );
                                Ok(SplitToolResult::simple(tool_name.as_str(), ui_content))
                            }
                        }
                    }
                    "list" => {
                        let summarizer = ListSummarizer::default();
                        match summarizer.summarize(&ui_content, None) {
                            Ok(llm_content) => {
                                debug!(
                                    tool = tools::UNIFIED_SEARCH,
                                    action = "list",
                                    ui_tokens = %summarizer.estimate_savings(&ui_content, &llm_content).1,
                                    llm_tokens = %summarizer.estimate_savings(&ui_content, &llm_content).0,
                                    savings_pct = %summarizer.estimate_savings(&ui_content, &llm_content).2,
                                    "Applied list summarization"
                                );
                                Ok(SplitToolResult::new(
                                    tool_name.as_str(),
                                    llm_content,
                                    ui_content,
                                ))
                            }
                            Err(e) => {
                                warn!(
                                    tool = tools::UNIFIED_SEARCH,
                                    action = "list",
                                    error = %e,
                                    "Failed to summarize list output, using simple result"
                                );
                                Ok(SplitToolResult::simple(tool_name.as_str(), ui_content))
                            }
                        }
                    }
                    _ => Ok(SplitToolResult::simple(tool_name.as_str(), ui_content)),
                }
            }
            tools::UNIFIED_FILE => {
                match tool_intent::unified_file_action(&args).unwrap_or("read") {
                    "read" => {
                        let mut metadata = args.clone();
                        if let Value::Object(map) = &mut metadata
                            && !map.contains_key("file_path")
                        {
                            let inferred_path = args
                                .get("path")
                                .or_else(|| args.get("file_path"))
                                .or_else(|| args.get("filepath"))
                                .or_else(|| args.get("target_path"))
                                .and_then(Value::as_str)
                                .map(str::to_string);
                            if let Some(path) = inferred_path {
                                map.insert("file_path".to_string(), Value::String(path));
                            }
                        }

                        let summarizer = ReadSummarizer::default();
                        match summarizer.summarize(&ui_content, Some(&metadata)) {
                            Ok(llm_content) => {
                                debug!(
                                    tool = tools::UNIFIED_FILE,
                                    action = "read",
                                    ui_tokens = %summarizer.estimate_savings(&ui_content, &llm_content).1,
                                    llm_tokens = %summarizer.estimate_savings(&ui_content, &llm_content).0,
                                    savings_pct = %summarizer.estimate_savings(&ui_content, &llm_content).2,
                                    "Applied unified_file read summarization"
                                );
                                Ok(SplitToolResult::new(
                                    tool_name.as_str(),
                                    llm_content,
                                    ui_content,
                                ))
                            }
                            Err(e) => {
                                warn!(
                                    tool = tools::UNIFIED_FILE,
                                    action = "read",
                                    error = %e,
                                    "Failed to summarize unified_file read output, using simple result"
                                );
                                Ok(SplitToolResult::simple(tool_name.as_str(), ui_content))
                            }
                        }
                    }
                    "write" | "edit" | "patch" | "move" | "copy" | "delete" => {
                        let summarizer = EditSummarizer::default();
                        match summarizer.summarize(&ui_content, None) {
                            Ok(llm_content) => {
                                debug!(
                                    tool = tools::UNIFIED_FILE,
                                    action = "mutate",
                                    ui_tokens = %summarizer.estimate_savings(&ui_content, &llm_content).1,
                                    llm_tokens = %summarizer.estimate_savings(&ui_content, &llm_content).0,
                                    savings_pct = %summarizer.estimate_savings(&ui_content, &llm_content).2,
                                    "Applied unified_file mutation summarization"
                                );
                                Ok(SplitToolResult::new(
                                    tool_name.as_str(),
                                    llm_content,
                                    ui_content,
                                ))
                            }
                            Err(e) => {
                                warn!(
                                    tool = tools::UNIFIED_FILE,
                                    action = "mutate",
                                    error = %e,
                                    "Failed to summarize unified_file mutation output, using simple result"
                                );
                                Ok(SplitToolResult::simple(tool_name.as_str(), ui_content))
                            }
                        }
                    }
                    _ => Ok(SplitToolResult::simple(tool_name.as_str(), ui_content)),
                }
            }
            tools::UNIFIED_EXEC => match tool_intent::unified_exec_action(&args).unwrap_or("run") {
                "run" | "code" => {
                    let summarizer = BashSummarizer::default();
                    let metadata = args.as_object().map(|_| args.clone());
                    match summarizer.summarize(&ui_content, metadata.as_ref()) {
                        Ok(llm_content) => {
                            debug!(
                                tool = tools::UNIFIED_EXEC,
                                action = "run",
                                ui_tokens = %summarizer.estimate_savings(&ui_content, &llm_content).1,
                                llm_tokens = %summarizer.estimate_savings(&ui_content, &llm_content).0,
                                savings_pct = %summarizer.estimate_savings(&ui_content, &llm_content).2,
                                "Applied unified_exec summarization"
                            );
                            Ok(SplitToolResult::new(
                                tool_name.as_str(),
                                llm_content,
                                ui_content,
                            ))
                        }
                        Err(e) => {
                            warn!(
                                tool = tools::UNIFIED_EXEC,
                                action = "run",
                                error = %e,
                                "Failed to summarize unified_exec output, using simple result"
                            );
                            Ok(SplitToolResult::simple(tool_name.as_str(), ui_content))
                        }
                    }
                }
                _ => Ok(SplitToolResult::simple(tool_name.as_str(), ui_content)),
            },
            tools::READ_FILE => {
                // Apply read file summarization
                let summarizer = ReadSummarizer::default();
                // Extract file path from args if available for better summary
                let metadata = args.as_object().map(|_| args.clone());
                match summarizer.summarize(&ui_content, metadata.as_ref()) {
                    Ok(llm_content) => {
                        debug!(
                            tool = tools::READ_FILE,
                            ui_tokens = %summarizer.estimate_savings(&ui_content, &llm_content).1,
                            llm_tokens = %summarizer.estimate_savings(&ui_content, &llm_content).0,
                            savings_pct = %summarizer.estimate_savings(&ui_content, &llm_content).2,
                            "Applied read file summarization"
                        );
                        Ok(SplitToolResult::new(
                            tool_name.as_str(),
                            llm_content,
                            ui_content,
                        ))
                    }
                    Err(e) => {
                        warn!(
                            tool = tools::READ_FILE,
                            error = %e,
                            "Failed to summarize read output, using simple result"
                        );
                        Ok(SplitToolResult::simple(tool_name.as_str(), ui_content))
                    }
                }
            }
            tools::RUN_PTY_CMD => {
                // Apply bash execution summarization
                let summarizer = BashSummarizer::default();
                // Pass command info from args if available
                let metadata = args.as_object().map(|_| args.clone());
                match summarizer.summarize(&ui_content, metadata.as_ref()) {
                    Ok(llm_content) => {
                        debug!(
                            tool = tools::RUN_PTY_CMD,
                            ui_tokens = %summarizer.estimate_savings(&ui_content, &llm_content).1,
                            llm_tokens = %summarizer.estimate_savings(&ui_content, &llm_content).0,
                            savings_pct = %summarizer.estimate_savings(&ui_content, &llm_content).2,
                            "Applied bash summarization"
                        );
                        Ok(SplitToolResult::new(
                            tool_name.as_str(),
                            llm_content,
                            ui_content,
                        ))
                    }
                    Err(e) => {
                        warn!(
                            tool = tools::RUN_PTY_CMD,
                            error = %e,
                            "Failed to summarize bash output, using simple result"
                        );
                        Ok(SplitToolResult::simple(tool_name.as_str(), ui_content))
                    }
                }
            }
            tools::WRITE_FILE | tools::EDIT_FILE | tools::APPLY_PATCH => {
                // Apply edit/write file summarization
                let summarizer = EditSummarizer::default();
                match summarizer.summarize(&ui_content, None) {
                    Ok(llm_content) => {
                        debug!(
                            tool = tool_name.as_str(),
                            ui_tokens = %summarizer.estimate_savings(&ui_content, &llm_content).1,
                            llm_tokens = %summarizer.estimate_savings(&ui_content, &llm_content).0,
                            savings_pct = %summarizer.estimate_savings(&ui_content, &llm_content).2,
                            "Applied edit summarization"
                        );
                        Ok(SplitToolResult::new(
                            tool_name.as_str(),
                            llm_content,
                            ui_content,
                        ))
                    }
                    Err(e) => {
                        warn!(
                            tool = tool_name.as_str(),
                            error = %e,
                            "Failed to summarize edit output, using simple result"
                        );
                        Ok(SplitToolResult::simple(tool_name.as_str(), ui_content))
                    }
                }
            }
            _ => {
                // No summarizer registered, use same content for both channels
                Ok(SplitToolResult::simple(tool_name.as_str(), ui_content))
            }
        }
    }
}
