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

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct CloudProduct {
    pub id: String,
    pub vendor: String,
    pub product_type: String,
    pub name: String,
    pub region: Option<String>,
    pub instance_id: Option<String>,
    pub endpoint: Option<String>,
    pub expire_at: Option<String>,
    pub status: String,
    pub config_data: String,
    pub notes: Option<String>,
    pub sort_order: i32,
    pub created_at: Option<String>,
    pub updated_at: Option<String>,
}

#[derive(Debug, Deserialize)]
pub struct SaveCloudProductInput {
    pub vendor: String,
    pub product_type: String,
    pub name: String,
    pub region: Option<String>,
    pub instance_id: Option<String>,
    pub endpoint: Option<String>,
    pub expire_at: Option<String>,
    pub status: String,
    pub config_data: Option<String>,
    pub notes: Option<String>,
    pub sort_order: Option<i32>,
}

fn row_to_cloud_product(row: &rusqlite::Row<'_>) -> rusqlite::Result<CloudProduct> {
    Ok(CloudProduct {
        id:           row.get(0)?,
        vendor:       row.get(1)?,
        product_type: row.get(2)?,
        name:         row.get(3)?,
        region:       row.get(4)?,
        instance_id:  row.get(5)?,
        endpoint:     row.get(6)?,
        expire_at:    row.get(7)?,
        status:       row.get(8)?,
        config_data:  row.get(9)?,
        notes:        row.get(10)?,
        sort_order:   row.get(11)?,
        created_at:   row.get(12)?,
        updated_at:   row.get(13)?,
    })
}

const SELECT_COLS: &str =
    "id, vendor, product_type, name, region, instance_id, endpoint, expire_at, \
     status, config_data, notes, sort_order, created_at, updated_at";

pub fn list_cloud_products(conn: &Connection) -> Vec<CloudProduct> {
    let sql = format!(
        "SELECT {SELECT_COLS} FROM cloud_products ORDER BY vendor, sort_order, name"
    );
    let mut stmt = match conn.prepare(&sql) {
        Ok(s) => s,
        Err(_) => return vec![],
    };
    stmt.query_map([], row_to_cloud_product)
        .map(|iter| iter.filter_map(|r| r.ok()).collect())
        .unwrap_or_default()
}

fn get_cloud_product_by_id(conn: &Connection, id: &str) -> Option<CloudProduct> {
    let sql = format!("SELECT {SELECT_COLS} FROM cloud_products WHERE id = ?1");
    conn.query_row(&sql, params![id], row_to_cloud_product).ok()
}

pub fn create_cloud_product(conn: &Connection, input: &SaveCloudProductInput) -> Result<CloudProduct, String> {
    let id = format!("cp-{}", uuid::Uuid::new_v4());
    let config_data = input.config_data.as_deref().unwrap_or("{}");
    conn.execute(
        "INSERT INTO cloud_products
            (id, vendor, product_type, name, region, instance_id, endpoint, expire_at,
             status, config_data, notes, sort_order)
         VALUES (?1,?2,?3,?4,?5,?6,?7,?8,?9,?10,?11,?12)",
        params![
            id, input.vendor, input.product_type, input.name,
            input.region, input.instance_id, input.endpoint, input.expire_at,
            input.status, config_data, input.notes,
            input.sort_order.unwrap_or(0)
        ],
    )
    .map_err(|e| e.to_string())?;
    get_cloud_product_by_id(conn, &id).ok_or_else(|| "创建后查询失败".into())
}

pub fn update_cloud_product(conn: &Connection, id: &str, input: &SaveCloudProductInput) -> Result<CloudProduct, String> {
    let config_data = input.config_data.as_deref().unwrap_or("{}");
    let rows = conn.execute(
        "UPDATE cloud_products
         SET vendor=?1, product_type=?2, name=?3, region=?4, instance_id=?5,
             endpoint=?6, expire_at=?7, status=?8, config_data=?9, notes=?10,
             sort_order=?11, updated_at=datetime('now')
         WHERE id=?12",
        params![
            input.vendor, input.product_type, input.name,
            input.region, input.instance_id, input.endpoint, input.expire_at,
            input.status, config_data, input.notes,
            input.sort_order.unwrap_or(0), id
        ],
    )
    .map_err(|e| e.to_string())?;
    if rows == 0 {
        return Err(format!("云产品 {} 不存在", id));
    }
    get_cloud_product_by_id(conn, id).ok_or_else(|| "更新后查询失败".into())
}

pub fn delete_cloud_product_fn(conn: &Connection, id: &str) -> Result<(), String> {
    conn.execute("DELETE FROM cloud_products WHERE id=?1", params![id])
        .map_err(|e| e.to_string())?;
    Ok(())
}

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

#[tauri::command]
pub fn get_cloud_products() -> Result<Vec<CloudProduct>, String> {
    let conn = crate::db::pool().get().map_err(|e| e.to_string())?;
    Ok(list_cloud_products(&conn))
}

#[tauri::command]
pub fn add_cloud_product(input: SaveCloudProductInput) -> Result<CloudProduct, String> {
    let conn = crate::db::pool().get().map_err(|e| e.to_string())?;
    create_cloud_product(&conn, &input)
}

#[tauri::command]
pub fn edit_cloud_product(id: String, input: SaveCloudProductInput) -> Result<CloudProduct, String> {
    let conn = crate::db::pool().get().map_err(|e| e.to_string())?;
    update_cloud_product(&conn, &id, &input)
}

#[tauri::command]
pub fn delete_cloud_product(id: String) -> Result<(), String> {
    let conn = crate::db::pool().get().map_err(|e| e.to_string())?;
    delete_cloud_product_fn(&conn, &id)
}
