use crate::db;
use crate::models::{DeployCommand, Space};
use uuid::Uuid;

// ── 空间管理 ────────────────────────────────────────────────

#[tauri::command]
pub fn get_spaces() -> Result<Vec<Space>, String> {
    let conn = db::pool().get().map_err(|e| e.to_string())?;
    let mut stmt = conn
        .prepare("SELECT id, name, is_current, created_at FROM spaces ORDER BY created_at ASC")
        .map_err(|e| e.to_string())?;
    let rows = stmt
        .query_map([], Space::from_row)
        .map_err(|e| e.to_string())?;
    rows.map(|r| r.map_err(|e| e.to_string())).collect()
}

#[tauri::command]
pub fn create_space(name: String) -> Result<Space, String> {
    let conn = db::pool().get().map_err(|e| e.to_string())?;
    let id = Uuid::new_v4().to_string();

    conn.execute_batch("BEGIN").map_err(|e| e.to_string())?;
    let result = (|| -> Result<(), String> {
        conn.execute("UPDATE spaces SET is_current = 0", [])
            .map_err(|e| e.to_string())?;
        // local_root 保留列但填空字符串（历史 NOT NULL 约束）
        conn.execute(
            "INSERT INTO spaces (id, name, local_root, is_current) VALUES (?1, ?2, '', 1)",
            rusqlite::params![id, name],
        )
        .map_err(|e| e.to_string())?;
        Ok(())
    })();

    if let Err(e) = result {
        let _ = conn.execute_batch("ROLLBACK");
        return Err(e);
    }
    conn.execute_batch("COMMIT").map_err(|e| e.to_string())?;

    let space = conn
        .query_row(
            "SELECT id, name, is_current, created_at FROM spaces WHERE id = ?1",
            rusqlite::params![id],
            Space::from_row,
        )
        .map_err(|e| e.to_string())?;
    Ok(space)
}

#[tauri::command]
pub fn update_space(id: String, name: String) -> Result<(), String> {
    let conn = db::pool().get().map_err(|e| e.to_string())?;
    conn.execute(
        "UPDATE spaces SET name = ?1 WHERE id = ?2",
        rusqlite::params![name, id],
    )
    .map_err(|e| e.to_string())?;
    Ok(())
}

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

#[tauri::command]
pub fn set_current_space(id: String) -> Result<(), String> {
    let conn = db::pool().get().map_err(|e| e.to_string())?;
    conn.execute("UPDATE spaces SET is_current = 0", [])
        .map_err(|e| e.to_string())?;
    conn.execute(
        "UPDATE spaces SET is_current = 1 WHERE id = ?1",
        rusqlite::params![id],
    )
    .map_err(|e| e.to_string())?;
    Ok(())
}

// ── 部署命令管理 ────────────────────────────────────────────

#[tauri::command]
pub fn get_deploy_commands(project_id: String) -> Result<Vec<DeployCommand>, String> {
    let conn = db::pool().get().map_err(|e| e.to_string())?;
    let mut stmt = conn
        .prepare("SELECT id, project_id, name, command, run_in FROM deploy_commands WHERE project_id = ?1")
        .map_err(|e| e.to_string())?;
    let rows = stmt
        .query_map(rusqlite::params![project_id], DeployCommand::from_row)
        .map_err(|e| e.to_string())?;
    rows.map(|r| r.map_err(|e| e.to_string())).collect()
}

#[tauri::command]
pub fn add_deploy_command(
    project_id: String,
    name: String,
    command: String,
    run_in: String,
) -> Result<DeployCommand, String> {
    let conn = db::pool().get().map_err(|e| e.to_string())?;
    let id = Uuid::new_v4().to_string();
    conn.execute(
        "INSERT INTO deploy_commands (id, project_id, name, command, run_in) VALUES (?1, ?2, ?3, ?4, ?5)",
        rusqlite::params![id, project_id, name, command, run_in],
    )
    .map_err(|e| e.to_string())?;
    let cmd = conn
        .query_row(
            "SELECT id, project_id, name, command, run_in FROM deploy_commands WHERE id = ?1",
            rusqlite::params![id],
            DeployCommand::from_row,
        )
        .map_err(|e| e.to_string())?;
    Ok(cmd)
}

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

/// 执行部署命令，返回输出内容
#[tauri::command]
pub fn execute_deploy(command: String, run_in: String, cwd: Option<String>) -> Result<String, String> {
    let mut cmd = if run_in == "wsl" {
        let mut c = crate::silent_cmd("wsl");
        c.args(["-e", "bash", "-c", &command]);
        c
    } else {
        let mut c = crate::silent_cmd("cmd");
        c.args(["/c", &command]);
        c
    };

    if let Some(dir) = cwd {
        cmd.current_dir(&dir);
    }

    let output = cmd.output();

    match output {
        Ok(out) => {
            let stdout = String::from_utf8_lossy(&out.stdout).to_string();
            let stderr = String::from_utf8_lossy(&out.stderr).to_string();
            if out.status.success() {
                Ok(if stdout.is_empty() { "执行完成".to_string() } else { stdout })
            } else {
                Err(if !stderr.is_empty() { stderr } else { stdout })
            }
        }
        Err(e) => Err(format!("启动进程失败: {}", e)),
    }
}
