use async_trait::async_trait;

#[derive(Debug, Clone)]
pub struct ToolResult {
    pub success: bool,
    pub output: String,
    pub error: Option<String>,
}

#[derive(Debug, Clone, Default)]
pub struct ToolContext {
    pub channel_name: Option<String>,
    pub sender_id: Option<String>,
    pub chat_id: Option<String>,
    pub session_id: Option<String>,
    pub topic_id: Option<String>,
    pub message_id: Option<String>,
    pub message_seq: Option<i64>,
    /// 子代理标识，用于标注消息来源
    pub subagent_description: Option<String>,
}

#[async_trait]
pub trait Tool: Send + Sync + 'static {
    fn name(&self) -> &str;
    fn description(&self) -> &str;
    fn parameters_schema(&self) -> serde_json::Value;
    async fn execute(&self, args: serde_json::Value) -> anyhow::Result<ToolResult>;

    async fn execute_with_context(
        &self,
        _context: &ToolContext,
        args: serde_json::Value,
    ) -> anyhow::Result<ToolResult> {
        self.execute(args).await
    }

    /// Whether this tool is side-effect free and safe to parallelize.
    fn read_only(&self) -> bool {
        false
    }

    /// Whether this tool can run alongside other concurrency-safe tools.
    fn concurrency_safe(&self) -> bool {
        self.read_only() && !self.exclusive()
    }

    /// Whether this tool should run alone even if concurrency is enabled.
    fn exclusive(&self) -> bool {
        false
    }
}
