use crate::db::pool;
use rusqlite::params;
use serde::{Deserialize, Serialize};
use std::process::Command as StdCommand;

// ── 数据结构 ──────────────────────────────────────────────────────────────────

#[derive(Debug, Serialize)]
pub struct ProjectTool {
    pub id: String,
    pub project_id: String,
    pub name: String,
    pub icon: String,
    pub exe_path: String,
    pub args: Option<String>,
    pub sort_order: i32,
}

#[derive(Debug, Deserialize)]
pub struct ProjectToolInput {
    pub name: String,
    pub icon: String,
    pub exe_path: String,
    pub args: Option<String>,
    pub sort_order: Option<i32>,
}

// ── Tauri 命令 ────────────────────────────────────────────────────────────────

/// 获取某个项目的所有工具
#[tauri::command]
pub fn get_project_tools(project_id: String) -> Result<Vec<ProjectTool>, String> {
    let conn = pool().get().map_err(|e| e.to_string())?;
    let mut stmt = conn
        .prepare(
            "SELECT id, project_id, name, icon, exe_path, args, sort_order
             FROM project_tools
             WHERE project_id = ?1
             ORDER BY sort_order ASC, rowid ASC",
        )
        .map_err(|e| e.to_string())?;
    let rows = stmt
        .query_map(params![project_id], |row| {
            Ok(ProjectTool {
                id:         row.get(0)?,
                project_id: row.get(1)?,
                name:       row.get(2)?,
                icon:       row.get(3)?,
                exe_path:   row.get(4)?,
                args:       row.get(5)?,
                sort_order: row.get(6)?,
            })
        })
        .map_err(|e| e.to_string())?
        .collect::<Result<Vec<_>, _>>()
        .map_err(|e| e.to_string());
    rows
}

/// 添加工具到项目
#[tauri::command]
pub fn add_project_tool(project_id: String, input: ProjectToolInput) -> Result<String, String> {
    let conn = pool().get().map_err(|e| e.to_string())?;
    let id = uuid::Uuid::new_v4().to_string();
    conn.execute(
        "INSERT INTO project_tools (id, project_id, name, icon, exe_path, args, sort_order)
         VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)",
        params![
            id,
            project_id,
            input.name,
            input.icon,
            input.exe_path,
            input.args,
            input.sort_order.unwrap_or(0),
        ],
    )
    .map_err(|e| e.to_string())?;
    Ok(id)
}

/// 更新工具信息
#[tauri::command]
pub fn update_project_tool(id: String, input: ProjectToolInput) -> Result<(), String> {
    let conn = pool().get().map_err(|e| e.to_string())?;
    conn.execute(
        "UPDATE project_tools
         SET name = ?1, icon = ?2, exe_path = ?3, args = ?4, sort_order = ?5
         WHERE id = ?6",
        params![
            input.name,
            input.icon,
            input.exe_path,
            input.args,
            input.sort_order.unwrap_or(0),
            id,
        ],
    )
    .map_err(|e| e.to_string())?;
    Ok(())
}

/// 删除项目工具
#[tauri::command]
pub fn remove_project_tool(id: String) -> Result<(), String> {
    let conn = pool().get().map_err(|e| e.to_string())?;
    conn.execute("DELETE FROM project_tools WHERE id = ?1", params![id])
        .map_err(|e| e.to_string())?;
    Ok(())
}

// ── 全局快启命令（写入 global_tools 表，无项目 FK 约束）────────────────────────

#[tauri::command]
pub fn get_global_tools() -> Result<Vec<ProjectTool>, String> {
    let conn = pool().get().map_err(|e| e.to_string())?;
    let mut stmt = conn
        .prepare(
            "SELECT id, name, icon, exe_path, args, sort_order
             FROM global_tools
             ORDER BY sort_order ASC, rowid ASC",
        )
        .map_err(|e| e.to_string())?;
    let rows = stmt
        .query_map([], |row| {
            Ok(ProjectTool {
                id:         row.get(0)?,
                project_id: "__global__".to_string(),
                name:       row.get(1)?,
                icon:       row.get(2)?,
                exe_path:   row.get(3)?,
                args:       row.get(4)?,
                sort_order: row.get(5)?,
            })
        })
        .map_err(|e| e.to_string())?
        .collect::<Result<Vec<_>, _>>()
        .map_err(|e| e.to_string());
    rows
}

#[tauri::command]
pub fn add_global_tool(input: ProjectToolInput) -> Result<String, String> {
    let conn = pool().get().map_err(|e| e.to_string())?;
    let id = uuid::Uuid::new_v4().to_string();
    conn.execute(
        "INSERT INTO global_tools (id, name, icon, exe_path, args, sort_order)
         VALUES (?1, ?2, ?3, ?4, ?5, ?6)",
        params![
            id,
            input.name,
            input.icon,
            input.exe_path,
            input.args,
            input.sort_order.unwrap_or(0),
        ],
    )
    .map_err(|e| e.to_string())?;
    Ok(id)
}

#[tauri::command]
pub fn update_global_tool(id: String, input: ProjectToolInput) -> Result<(), String> {
    let conn = pool().get().map_err(|e| e.to_string())?;
    conn.execute(
        "UPDATE global_tools
         SET name = ?1, icon = ?2, exe_path = ?3, args = ?4, sort_order = ?5
         WHERE id = ?6",
        params![
            input.name,
            input.icon,
            input.exe_path,
            input.args,
            input.sort_order.unwrap_or(0),
            id,
        ],
    )
    .map_err(|e| e.to_string())?;
    Ok(())
}

#[tauri::command]
pub fn remove_global_tool(id: String) -> Result<(), String> {
    let conn = pool().get().map_err(|e| e.to_string())?;
    conn.execute("DELETE FROM global_tools WHERE id = ?1", params![id])
        .map_err(|e| e.to_string())?;
    Ok(())
}

/// 启动工具（通用：exe 路径 + 可选参数）
#[tauri::command]
pub fn launch_tool(exe_path: String, args: Option<String>) -> Result<(), String> {
    #[cfg(target_os = "windows")]
    {
        use std::os::windows::process::CommandExt;
        let mut cmd = StdCommand::new("cmd");
        cmd.args(["/c", &exe_path]);
        if let Some(a) = &args {
            let trimmed = a.trim();
            if !trimmed.is_empty() {
                cmd.raw_arg(trimmed);
            }
        }
        cmd.spawn().map_err(|e| format!("启动失败: {e}"))?;
    }
    #[cfg(not(target_os = "windows"))]
    {
        let mut cmd = StdCommand::new(&exe_path);
        if let Some(a) = &args {
            let trimmed = a.trim();
            if !trimmed.is_empty() {
                cmd.args(trimmed.split_whitespace());
            }
        }
        cmd.spawn().map_err(|e| format!("启动失败: {e}"))?;
    }
    Ok(())
}
