use rusqlite::{params, Connection};
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct CloudDatabase {
    pub id: String,
    pub product_id: String,
    pub name: String,
    pub db_driver: String,
    pub username: Option<String>,
    pub password: Option<String>,
    pub charset: Option<String>,
    pub notes: Option<String>,
    pub sort_order: i32,
    pub created_at: Option<String>,
    pub updated_at: Option<String>,
}

#[derive(Debug, Deserialize)]
pub struct SaveCloudDatabaseInput {
    pub product_id: String,
    pub name: String,
    pub db_driver: String,
    pub username: Option<String>,
    pub password: Option<String>,
    pub charset: Option<String>,
    pub notes: Option<String>,
    pub sort_order: Option<i32>,
}

fn row_to_db(row: &rusqlite::Row<'_>) -> rusqlite::Result<CloudDatabase> {
    Ok(CloudDatabase {
        id:         row.get(0)?,
        product_id: row.get(1)?,
        name:       row.get(2)?,
        db_driver:  row.get(3)?,
        username:   row.get(4)?,
        password:   row.get(5)?,
        charset:    row.get(6)?,
        notes:      row.get(7)?,
        sort_order: row.get(8)?,
        created_at: row.get(9)?,
        updated_at: row.get(10)?,
    })
}

const COLS: &str =
    "id, product_id, name, db_driver, username, password, charset, notes, sort_order, created_at, updated_at";

fn get_by_id(conn: &Connection, id: &str) -> Option<CloudDatabase> {
    let sql = format!("SELECT {COLS} FROM cloud_db_databases WHERE id = ?1");
    conn.query_row(&sql, params![id], row_to_db).ok()
}

// ── Tauri commands ───────────────────────────────────────────────────────────

#[tauri::command]
pub fn get_cloud_databases(product_id: String) -> Result<Vec<CloudDatabase>, String> {
    let conn = crate::db::pool().get().map_err(|e| e.to_string())?;
    let sql = format!(
        "SELECT {COLS} FROM cloud_db_databases WHERE product_id = ?1 ORDER BY sort_order, name"
    );
    let mut stmt = conn.prepare(&sql).map_err(|e| e.to_string())?;
    let rows = stmt
        .query_map(params![product_id], row_to_db)
        .map_err(|e| e.to_string())?
        .filter_map(|r| r.ok())
        .collect();
    Ok(rows)
}

#[tauri::command]
pub fn add_cloud_database(input: SaveCloudDatabaseInput) -> Result<CloudDatabase, String> {
    let conn = crate::db::pool().get().map_err(|e| e.to_string())?;
    let id = format!("cdb-{}", uuid::Uuid::new_v4());
    conn.execute(
        "INSERT INTO cloud_db_databases
            (id, product_id, name, db_driver, username, password, charset, notes, sort_order)
         VALUES (?1,?2,?3,?4,?5,?6,?7,?8,?9)",
        params![
            id, input.product_id, input.name, input.db_driver,
            input.username, input.password,
            input.charset.as_deref().unwrap_or("utf8mb4"),
            input.notes, input.sort_order.unwrap_or(0)
        ],
    )
    .map_err(|e| e.to_string())?;
    get_by_id(&conn, &id).ok_or_else(|| "创建后查询失败".into())
}

#[tauri::command]
pub fn edit_cloud_database(id: String, input: SaveCloudDatabaseInput) -> Result<CloudDatabase, String> {
    let conn = crate::db::pool().get().map_err(|e| e.to_string())?;
    let rows = conn.execute(
        "UPDATE cloud_db_databases
         SET name=?1, db_driver=?2, username=?3, password=?4, charset=?5,
             notes=?6, sort_order=?7, updated_at=datetime('now')
         WHERE id=?8",
        params![
            input.name, input.db_driver, input.username, input.password,
            input.charset.as_deref().unwrap_or("utf8mb4"),
            input.notes, input.sort_order.unwrap_or(0), id
        ],
    )
    .map_err(|e| e.to_string())?;
    if rows == 0 { return Err(format!("数据库 {} 不存在", id)); }
    get_by_id(&conn, &id).ok_or_else(|| "更新后查询失败".into())
}

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