/// Tool Registry - Thread-safe tool storage and lookup

use crate::tool::Tool;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::RwLock;
use tracing::{debug, warn};
use uuid::Uuid;

/// Tool execution result (for backward compatibility with ToolExecutor)
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ToolResult {
    pub tool_id: String,
    pub execution_id: Uuid,
    pub success: bool,
    pub output: serde_json::Value,
    pub error: Option<String>,
    pub execution_time_ms: u64,
    pub cached: bool,
}

/// Tool execution context (for backward compatibility)
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ToolContext {
    pub agent_id: String,
    pub step_id: Option<String>,
    pub seed: u64,
    pub metadata: HashMap<String, String>,
}

/// Tool execution errors (for backward compatibility)
#[derive(Debug, thiserror::Error)]
pub enum ToolError {
    #[error("Tool execution failed: {0}")]
    ExecutionError(String),
    
    #[error("Invalid parameters: {0}")]
    InvalidParameters(String),
    
    #[error("Tool timeout")]
    Timeout,
    
    #[error("Tool not found: {0}")]
    NotFound(String),
    
    #[error("Serialization error: {0}")]
    SerializationError(#[from] serde_json::Error),
}

/// Thread-safe registry mapping tool names to tool implementations
pub struct ToolRegistry {
    tools: Arc<RwLock<HashMap<&'static str, Arc<dyn Tool>>>>,
}

impl ToolRegistry {
    /// Create a new empty tool registry
    pub fn new() -> Self {
        Self {
            tools: Arc::new(RwLock::new(HashMap::new())),
        }
    }
    
    /// Register a tool
    /// 
    /// # Arguments
    /// * `tool` - Tool implementation wrapped in Arc
    /// 
    /// # Returns
    /// * `true` if registered successfully
    /// * `false` if tool with same name already exists
    pub async fn register(&self, tool: Arc<dyn Tool>) -> bool {
        let name = tool.name();
        let mut tools = self.tools.write().await;
        
        if tools.contains_key(name) {
            warn!("Tool '{}' already registered, overwriting", name);
        }
        
        tools.insert(name, tool);
        debug!("Registered tool: {}", name);
        true
    }
    
    /// Get a tool by name
    /// 
    /// # Arguments
    /// * `name` - Tool name
    /// 
    /// # Returns
    /// * `Some(Arc<dyn Tool>)` if found
    /// * `None` if not found
    pub async fn get(&self, name: &str) -> Option<Arc<dyn Tool>> {
        let tools = self.tools.read().await;
        tools.get(name).cloned()
    }
    
    /// Check if a tool exists
    pub async fn exists(&self, name: &str) -> bool {
        let tools = self.tools.read().await;
        tools.contains_key(name)
    }
    
    /// List all registered tool names
    pub async fn list(&self) -> Vec<&'static str> {
        let tools = self.tools.read().await;
        tools.keys().copied().collect()
    }
    
    /// Get count of registered tools
    pub async fn count(&self) -> usize {
        let tools = self.tools.read().await;
        tools.len()
    }
    
    /// Unregister a tool
    pub async fn unregister(&self, name: &str) -> bool {
        let mut tools = self.tools.write().await;
        tools.remove(name).is_some()
    }
    
    /// Clear all tools
    pub async fn clear(&self) {
        let mut tools = self.tools.write().await;
        tools.clear();
        debug!("Cleared all tools from registry");
    }
}

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