use std::collections::HashMap;

use crate::domain::tools::{Tool, ToolFunction};

use super::traits::Tool as ToolTrait;

pub struct ToolRegistry {
    tools: HashMap<String, Box<dyn ToolTrait>>,
}

impl ToolRegistry {
    pub fn new() -> Self {
        Self {
            tools: HashMap::new(),
        }
    }

    pub fn register<T: ToolTrait + 'static>(&mut self, tool: T) {
        self.tools.insert(tool.name().to_string(), Box::new(tool));
    }

    pub fn get(&self, name: &str) -> Option<&Box<dyn ToolTrait>> {
        self.tools.get(name)
    }

    /// Get all registered tools.
    /// Used for concurrent tool execution when we need to look up tools by name.
    pub fn get_all(&self) -> Vec<&Box<dyn ToolTrait>> {
        self.tools.values().collect()
    }

    pub fn get_definitions(&self) -> Vec<Tool> {
        self.tools
            .values()
            .map(|tool| Tool {
                tool_type: "function".to_string(),
                function: ToolFunction {
                    name: tool.name().to_string(),
                    description: tool.description().to_string(),
                    parameters: tool.parameters_schema(),
                },
            })
            .collect()
    }

    pub fn has_tools(&self) -> bool {
        !self.tools.is_empty()
    }

    pub fn tool_names(&self) -> Vec<String> {
        self.tools.keys().cloned().collect()
    }
}

impl Default for ToolRegistry {
    fn default() -> Self {
        Self::new()
    }
}
