use crate::error::{AppError, AppResult};
use serde::{Deserialize, Serialize};
use std::process::Command;
use tauri_plugin_shell::ShellExt;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SuperviseResult {
    pub success: bool,
    pub stdout: String,
    pub stderr: String,
}

pub async fn run_supervise_magic_raw(
    app: tauri::AppHandle,
    action: &str,
    args: &[&str],
) -> AppResult<SuperviseResult> {
    let sidecar = app
        .shell()
        .sidecar("supervise-magic")
        .map_err(|e| AppError::new(format!("Failed to locate supervise-magic sidecar: {}", e)))?;

    let mut cmd = sidecar.arg(action);
    for a in args {
        cmd = cmd.arg(a);
    }

    let output = cmd
        .output()
        .await
        .map_err(|e| AppError::new(format!("Failed to run supervise-magic: {}", e)))?;

    Ok(SuperviseResult {
        success: output.status.success(),
        stdout: String::from_utf8_lossy(&output.stdout).to_string(),
        stderr: String::from_utf8_lossy(&output.stderr).to_string(),
    })
}

#[tauri::command]
pub async fn run_supervise_magic(
    app: tauri::AppHandle,
    action: String,
    args: Option<Vec<String>>,
) -> AppResult<SuperviseResult> {
    let args: Vec<&str> = args.as_ref().map(|v| v.iter().map(|s| s.as_str()).collect()).unwrap_or_default();
    run_supervise_magic_raw(app, &action, &args).await
}

// Synchronous fallback for direct shell execution
#[allow(dead_code)]
pub fn run_supervise_magic_sync(binary_path: &str, action: &str) -> AppResult<SuperviseResult> {
    let output = Command::new(binary_path)
        .arg(action)
        .output()
        .map_err(|e| AppError::new(format!("Failed to run supervise-magic: {}", e)))?;

    Ok(SuperviseResult {
        success: output.status.success(),
        stdout: String::from_utf8_lossy(&output.stdout).to_string(),
        stderr: String::from_utf8_lossy(&output.stderr).to_string(),
    })
}
