use rexie::{ObjectStore, Rexie, TransactionMode};
use js_sys::Uint8Array;
use wasm_bindgen::JsValue;

const DB_NAME: &str = "kipina_qwen_db";
const STORE_NAME: &str = "weights_store";

/// Kytketään yhteys IndexedDB:hen (tai luodaan store jos sitä ei ole)
pub async fn get_db() -> Result<Rexie, rexie::Error> {
    Rexie::builder(DB_NAME)
        .version(1)
        .add_object_store(ObjectStore::new(STORE_NAME))
        .build()
        .await
}

/// Tallennetaan binääridata (esim. .safetensors lohko tai tokenizer.json string) IndexedDB-välimuistiin
pub async fn save_to_idb(key: &str, data: &[u8]) -> Result<(), String> {
    let db = get_db().await.map_err(|e| format!("DB Error: {}", e))?;
    let transaction = db
        .transaction(&[STORE_NAME], TransactionMode::ReadWrite)
        .map_err(|e| format!("Tx Error: {}", e))?;
        
    let store = transaction.store(STORE_NAME).map_err(|e| format!("Store Error: {}", e))?;
    
    // Konvertoidaan Rust u8-taulukko JS Uint8Array:ksi, joka on turvallisin blob IDB:lle
    let js_data = Uint8Array::from(data);
    
    store.put(&js_data, Some(&JsValue::from_str(key)))
         .await
         .map_err(|e| format!("Put Error: {:?}", e))?;
         
    transaction.done().await.map_err(|e| format!("Done Error: {}", e))?;
    Ok(())
}

/// Haetaan tallennettu data IndexedDB:stä key-arvon perusteella
pub async fn load_from_idb(key: &str) -> Result<Option<Vec<u8>>, String> {
    let db = get_db().await.map_err(|e| format!("DB Error: {}", e))?;
    let transaction = db
        .transaction(&[STORE_NAME], TransactionMode::ReadOnly)
        .map_err(|e| format!("Tx Error: {}", e))?;
        
    let store = transaction.store(STORE_NAME).map_err(|e| format!("Store Error: {}", e))?;
    let js_val_req = store.get(JsValue::from_str(key)).await.map_err(|e| format!("Get Error: {:?}", e))?;
    
    let js_val = match js_val_req {
        Some(val) => val,
        None => return Ok(None),
    };
    
    if js_val.is_undefined() || js_val.is_null() {
        return Ok(None);
    }
    
    // Ladataan JS muisti-blockista suoraan Rustin Veg:giksi
    let arr = Uint8Array::new(&js_val);
    let mut vec = vec![0; arr.length() as usize];
    arr.copy_to(&mut vec);
    
    Ok(Some(vec))
}
