use std::sync::Arc;

use async_trait::async_trait;

use crate::config::McpToolSettings;
use crate::tools::{Tool, ToolResult};

use super::{McpConnection, qualified_tool_name};

pub struct McpToolWrapper {
    full_name: String,
    description: String,
    parameters_schema: serde_json::Value,
    original_tool_name: String,
    connection: Arc<McpConnection>,
    settings: McpToolSettings,
}

impl McpToolWrapper {
    pub fn new(
        server_name: &str,
        original_tool_name: String,
        description: String,
        parameters_schema: serde_json::Value,
        connection: Arc<McpConnection>,
        settings: McpToolSettings,
    ) -> Self {
        Self {
            full_name: qualified_tool_name(server_name, &original_tool_name),
            description,
            parameters_schema,
            original_tool_name,
            connection,
            settings,
        }
    }
}

#[async_trait]
impl Tool for McpToolWrapper {
    fn name(&self) -> &str {
        &self.full_name
    }

    fn description(&self) -> &str {
        &self.description
    }

    fn parameters_schema(&self) -> serde_json::Value {
        self.parameters_schema.clone()
    }

    fn read_only(&self) -> bool {
        self.settings.read_only
    }

    fn exclusive(&self) -> bool {
        self.settings.exclusive
    }

    async fn execute(&self, args: serde_json::Value) -> anyhow::Result<ToolResult> {
        self.connection
            .call_tool(&self.original_tool_name, args)
            .await
    }
}
