use serde::Deserialize;
use serde_json::json;

use super::{common, ToolResult};

#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct RunParams {
    pub command: Vec<String>,
}

pub async fn execute(params: RunParams) -> ToolResult {
    common::validate_command(&params.command)?;
    let command = params.command;
    tokio::task::spawn_blocking(move || -> Result<(), String> {
        let cwd = std::env::current_dir().map_err(|e| e.to_string())?;
        let mappings = envseal::envseal_file::discover_and_load(&cwd)
            .map_err(|e| e.to_string())?
            .ok_or_else(|| {
                "no .envseal file found in the working directory. create one with `envseal init` or specify secrets explicitly. auto-mapping all vault secrets is not permitted.".to_string()
            })?;
        let refs: Vec<(&str, &str)> = mappings
            .iter()
            .map(|m| (m.secret_name.as_str(), m.env_var.as_str()))
            .collect();
        let vault = envseal::vault::Vault::open_default().map_err(|e| e.to_string())?;
        let options = envseal::inject::InjectExecOptions {
            isolate_stdio: true,
        };
        envseal::inject::execute_multi_with_options(&vault, &refs, &command, options)
            .map_err(|e| e.to_string())?;
        Ok(())
    })
    .await
    .map_err(|e| format!("run task failed: {e}"))??;

    Ok(json!({
        "status": "completed",
        "mode": "run",
        "exit_code": 0
    }))
}
