use std::sync::Arc;
use std::sync::atomic::AtomicU8;

use stynx_code_config::HooksConfig;
use stynx_code_errors::AppResult;
use stynx_code_types::{InterruptBehavior, PermissionChecker, PermissionLevel, Tool};
use stynx_code_tools::ToolRegistry;
use serde_json::{Value, json};

use super::sub_engine::SubEngine;

const AGENT_SYSTEM: &str = "You are a specialized sub-agent. Complete the given task efficiently and concisely. Use tools as needed. Report results clearly.";

pub struct AgentTool(SubEngine);

impl AgentTool {
    pub fn new(
        provider: Arc<dyn stynx_code_types::Provider>,
        registry: Arc<ToolRegistry>,
        permission: Arc<dyn PermissionChecker>,
        mode: Arc<AtomicU8>,
        hooks: HooksConfig,
    ) -> Self {
        Self(SubEngine { provider, registry, permission, mode, hooks })
    }
}

#[async_trait::async_trait]
impl Tool for AgentTool {
    fn name(&self) -> &str { "agent" }

    fn description(&self) -> &str {
        "Spawn a sub-agent to handle a complex, independent task. Use this to delegate research, analysis, or multi-step work that can run autonomously. Returns the agent's final response."
    }

    fn input_schema(&self) -> Value {
        json!({
            "type": "object",
            "properties": {
                "task": {
                    "type": "string",
                    "description": "The task description for the sub-agent"
                },
                "system_prompt": {
                    "type": "string",
                    "description": "Optional custom system prompt override for the sub-agent"
                }
            },
            "required": ["task"]
        })
    }

    fn permission_level(&self) -> PermissionLevel { PermissionLevel::Dangerous }

    fn interrupt_behavior(&self) -> InterruptBehavior { InterruptBehavior::Cancel }

    async fn execute(&self, input: Value) -> AppResult<String> {
        let task = input["task"].as_str().unwrap_or("").to_string();
        let system = input["system_prompt"].as_str().unwrap_or(AGENT_SYSTEM);
        self.0.run("agent", system, &task).await
    }
}
