// Rôle : encapsule les opérations IndexedDB génériques utilisées par les toolboxes.
const DB_NAME = "sokkog";
const DB_VERSION = 1;
const KV_STORE = "kv";
const MODULE_STORE = "modules";

let dbPromise;

function openDatabase() {
  if (dbPromise) return dbPromise;
  dbPromise = new Promise((resolve, reject) => {
    const request = indexedDB.open(DB_NAME, DB_VERSION);

    request.onupgradeneeded = () => {
      const db = request.result;
      if (!db.objectStoreNames.contains(KV_STORE)) db.createObjectStore(KV_STORE);
      if (!db.objectStoreNames.contains(MODULE_STORE)) db.createObjectStore(MODULE_STORE, { keyPath: "key" });
    };

    request.onsuccess = () => resolve(request.result);
    request.onerror = () => reject(request.error);
  });
  return dbPromise;
}

function requestToPromise(request) {
  return new Promise((resolve, reject) => {
    request.onsuccess = () => resolve(request.result);
    request.onerror = () => reject(request.error);
  });
}

async function storeRequest(storeName, mode, callback) {
  const db = await openDatabase();
  const transaction = db.transaction(storeName, mode);
  const store = transaction.objectStore(storeName);
  return requestToPromise(callback(store));
}

export async function getValue(key, fallback) {
  const value = await storeRequest(KV_STORE, "readonly", (store) => store.get(key));
  return value == null ? fallback : value;
}

export async function setValue(key, value) {
  await storeRequest(KV_STORE, "readwrite", (store) => store.put(value, key));
}

export async function getToolboxes() {
  return getValue("toolboxes", []);
}

export async function setToolboxes(toolboxes) {
  await setValue("toolboxes", toolboxes);
}

export async function getLinks() {
  return getValue("links", {});
}

export async function setLinks(links) {
  await setValue("links", links);
}

export async function getSetting(key, fallback) {
  return getValue(`setting:${key}`, fallback);
}

export async function setSetting(key, value) {
  await setValue(`setting:${key}`, value);
}

export async function getAllModuleData() {
  return storeRequest(MODULE_STORE, "readonly", (store) => store.getAll());
}

export async function setModuleData(key, data) {
  await storeRequest(MODULE_STORE, "readwrite", (store) => store.put({ key, data }));
}

export async function removeModuleData(key) {
  await storeRequest(MODULE_STORE, "readwrite", (store) => store.delete(key));
}

export async function removeModuleDataKeys(keys) {
  if (!keys.length) return;
  const db = await openDatabase();
  await new Promise((resolve, reject) => {
    const transaction = db.transaction(MODULE_STORE, "readwrite");
    const store = transaction.objectStore(MODULE_STORE);
    keys.forEach((key) => store.delete(key));
    transaction.oncomplete = () => resolve();
    transaction.onerror = () => reject(transaction.error);
    transaction.onabort = () => reject(transaction.error);
  });
}

export async function getStorageEstimate() {
  if (!navigator.storage?.estimate) return { usage: 0, quota: 0 };
  return navigator.storage.estimate();
}
