//! WASM-only debug bindings for the vault extension
#![cfg(target_arch = "wasm32")]

use wasm_bindgen::prelude::*;
use crate::{SESSION_MANAGER, SESSION_PASSWORD};

/// Debugging function to check if keypairs can be listed
#[wasm_bindgen]
pub async fn list_keypairs_debug() -> Result<JsValue, JsValue> {
    use js_sys::{Array, Object};
    use web_sys::console;
    console::log_1(&"Debug listing keypairs...".into());
    let session_ptr = SESSION_MANAGER.with(|cell| {
        let has_session = cell.borrow().is_some();
        console::log_1(&format!("Has session: {}", has_session).into());
        cell.borrow().as_ref().map(|s| s as *const _)
    });
    let password_opt = SESSION_PASSWORD.with(|pw| {
        let has_pw = pw.borrow().is_some();
        console::log_1(&format!("Has password: {}", has_pw).into());
        pw.borrow().clone()
    });
    if session_ptr.is_none() {
        return Err(JsValue::from_str("Session not initialized in debug function"));
    }
    if password_opt.is_none() {
        return Err(JsValue::from_str("Session password not set in debug function"));
    }
    let session: &vault::session::SessionManager<kvstore::wasm::WasmStore> = unsafe { &*session_ptr.unwrap() };
    let password = password_opt.unwrap();
    match session.current_keyspace_name() {
        Some(ks) => {
            let vault = session.get_vault();
            match vault.list_keypairs(ks, &password).await {
                Ok(keypairs) => {
                    console::log_1(&format!("Found {} keypairs", keypairs.len()).into());
                    let array = Array::new();
                    for (id, key_type) in keypairs {
                        let obj = Object::new();
                        js_sys::Reflect::set(&obj, &JsValue::from_str("id"), &JsValue::from_str(&id)).unwrap();
                        js_sys::Reflect::set(&obj, &JsValue::from_str("type"), &JsValue::from_str(&format!("{:?}", key_type))).unwrap();
                        array.push(&obj);
                    }
                    return Ok(array.into());
                }
                Err(e) => {
                    console::error_1(&format!("Error listing keypairs in debug function: {}", e).into());
                    return Err(JsValue::from_str(&format!("Error listing keypairs: {}", e)));
                }
            }
        }
        None => {
            console::error_1(&"No keyspace selected in debug function".into());
            return Err(JsValue::from_str("No keyspace selected"));
        }
    }
}

#[wasm_bindgen]
pub async fn check_indexeddb() -> Result<JsValue, JsValue> {
    #[cfg(not(target_arch = "wasm32"))]
    {
        return Err(JsValue::from_str(
            "IndexedDB check only available in browser context",
        ));
    }

    {
        use js_sys::Object;
        use kvstore::traits::KVStore;
        use kvstore::wasm::WasmStore;
        use web_sys::console; // Import the trait so we can use its methods

        console::log_1(&"Checking IndexedDB availability...".into());

        // Check if window.indexedDB is available
        if js_sys::eval("typeof window.indexedDB")
            .map_err(|e| {
                console::error_1(&format!("Error checking IndexedDB: {:?}", e).into());
                JsValue::from_str(&format!("Error checking IndexedDB: {:?}", e))
            })?
            .as_string()
            .unwrap_or_default()
            == "undefined"
        {
            console::error_1(&"IndexedDB is not available in this browser".into());
            return Err(JsValue::from_str(
                "IndexedDB is not available in this browser",
            ));
        }

        // Try to create a test database
        match WasmStore::open("db_test").await {
            Ok(store) => {
                console::log_1(&"Successfully opened test database".into());

                // Try to write and read a value to ensure it works
                let test_key = "test_key";
                let test_value = "test_value";

                // Use the KVStore trait methods
                if let Err(e) = store.set(test_key, test_value.as_bytes()).await {
                    console::error_1(&format!("Failed to write to IndexedDB: {}", e).into());
                    return Err(JsValue::from_str(&format!(
                        "Failed to write to IndexedDB: {}",
                        e
                    )));
                }

                // Get the value and handle the Option<Vec<u8>> properly
                match store.get(test_key).await {
                    Ok(maybe_value) => match maybe_value {
                        Some(value) => {
                            let value_str = String::from_utf8_lossy(&value);
                            if value_str == test_value {
                                console::log_1(
                                    &"Successfully read test value from IndexedDB".into(),
                                );
                            } else {
                                console::error_1(
                                    &format!(
                                        "IndexedDB test value mismatch: expected {}, got {}",
                                        test_value, value_str
                                    )
                                    .into(),
                                );
                                return Err(JsValue::from_str("IndexedDB test value mismatch"));
                            }
                        }
                        None => {
                            console::error_1(&"IndexedDB test key not found after writing".into());
                            return Err(JsValue::from_str(
                                "IndexedDB test key not found after writing",
                            ));
                        }
                    },
                    Err(e) => {
                        console::error_1(&format!("Failed to read from IndexedDB: {}", e).into());
                        return Err(JsValue::from_str(&format!(
                            "Failed to read from IndexedDB: {}",
                            e
                        )));
                    }
                }

                // Return success with the available database names
                let result = Object::new();
                js_sys::Reflect::set(
                    &result,
                    &JsValue::from_str("status"),
                    &JsValue::from_str("success"),
                )
                .unwrap();
                js_sys::Reflect::set(
                    &result,
                    &JsValue::from_str("message"),
                    &JsValue::from_str("IndexedDB is working properly"),
                )
                .unwrap();

                return Ok(result.into());
            }
            Err(e) => {
                console::error_1(&format!("Failed to open IndexedDB test database: {}", e).into());
                return Err(JsValue::from_str(&format!(
                    "Failed to open test database: {}",
                    e
                )));
            }
        }
    }
}