/* ===========================================================
   Reiktable — store (localStorage), toasts, IndexedDB for PDFs
   Exposes: window.Store, window.useStore, window.toast,
            window.Toasts, window.PDFDB
   =========================================================== */
(function () {
  const KEY = "reiktable.v1";

  function load() {
    try {
      const raw = localStorage.getItem(KEY);
      if (raw) return JSON.parse(raw);
    } catch (e) {}
    return JSON.parse(JSON.stringify(window.SEED));
  }
  function save(s) {
    try { localStorage.setItem(KEY, JSON.stringify(s)); } catch (e) {}
  }

  let state = load();
  const subs = new Set();
  function emit() { subs.forEach(fn => fn(state)); }

  const Store = {
    get() { return state; },
    set(next) {
      state = typeof next === "function" ? next(state) : next;
      save(state); emit();
    },
    update(mutator) {
      const draft = JSON.parse(JSON.stringify(state));
      mutator(draft);
      state = draft; save(state); emit();
    },
    subscribe(fn) { subs.add(fn); return () => subs.delete(fn); },
    reset() { state = JSON.parse(JSON.stringify(window.SEED)); save(state); emit(); },
    exportJSON() {
      const blob = new Blob([JSON.stringify(state, null, 2)], { type: "application/json" });
      const url = URL.createObjectURL(blob);
      const a = document.createElement("a");
      a.href = url; a.download = "reiktable-campaign.json"; a.click();
      setTimeout(() => URL.revokeObjectURL(url), 1000);
    },
    importJSON(file) {
      return new Promise((res, rej) => {
        const r = new FileReader();
        r.onload = () => {
          try { Store.set(JSON.parse(r.result)); res(); }
          catch (e) { rej(e); }
        };
        r.onerror = rej; r.readAsText(file);
      });
    },
  };
  window.Store = Store;

  // ---- React hook ----
  window.useStore = function () {
    const [s, setS] = React.useState(state);
    React.useEffect(() => Store.subscribe(setS), []);
    return [s, Store.update, Store.set];
  };

  // ---- Toasts ----
  const toastSubs = new Set();
  let toastList = [];
  window.toast = function (msg, kind) {
    const id = Math.random().toString(36).slice(2);
    toastList = [...toastList, { id, msg, kind: kind || "" }];
    toastSubs.forEach(fn => fn(toastList));
    setTimeout(() => {
      toastList = toastList.filter(t => t.id !== id);
      toastSubs.forEach(fn => fn(toastList));
    }, 3200);
  };
  window.Toasts = function () {
    const [list, setList] = React.useState(toastList);
    React.useEffect(() => { toastSubs.add(setList); return () => toastSubs.delete(setList); }, []);
    return (
      <div className="toast-wrap">
        {list.map(t => <div key={t.id} className={"toast " + t.kind}>{t.msg}</div>)}
      </div>
    );
  };

  // ---- IndexedDB for rulebook PDFs (blobs can be large) ----
  const DBNAME = "reiktable-pdfs", STORE = "books";
  function openDB() {
    return new Promise((res, rej) => {
      const req = indexedDB.open(DBNAME, 1);
      req.onupgradeneeded = () => {
        const db = req.result;
        if (!db.objectStoreNames.contains(STORE)) db.createObjectStore(STORE, { keyPath: "id" });
      };
      req.onsuccess = () => res(req.result);
      req.onerror = () => rej(req.error);
    });
  }
  window.PDFDB = {
    async put(rec) {
      const db = await openDB();
      return new Promise((res, rej) => {
        const tx = db.transaction(STORE, "readwrite");
        tx.objectStore(STORE).put(rec);
        tx.oncomplete = res; tx.onerror = () => rej(tx.error);
      });
    },
    async get(id) {
      const db = await openDB();
      return new Promise((res, rej) => {
        const tx = db.transaction(STORE, "readonly");
        const r = tx.objectStore(STORE).get(id);
        r.onsuccess = () => res(r.result); r.onerror = () => rej(r.error);
      });
    },
    async all() {
      const db = await openDB();
      return new Promise((res, rej) => {
        const tx = db.transaction(STORE, "readonly");
        const r = tx.objectStore(STORE).getAll();
        r.onsuccess = () => res(r.result || []); r.onerror = () => rej(r.error);
      });
    },
    async del(id) {
      const db = await openDB();
      return new Promise((res, rej) => {
        const tx = db.transaction(STORE, "readwrite");
        tx.objectStore(STORE).delete(id);
        tx.oncomplete = res; tx.onerror = () => rej(tx.error);
      });
    },
  };
})();
