/* store.jsx — app data: seed + persistence + actions.
   Metadata (ratings/status/notes/albums/projects) -> localStorage.
   Uploaded image bytes -> IndexedDB (survive reload).
   Generated demo photos resolve from a numeric seed (photos.js). */

const LS_KEY = "cp_data_v1";

/* ---------- tiny IndexedDB blob store for uploads ---------- */
const idb = {
  _db: null,
  open() {
    if (this._db) return Promise.resolve(this._db);
    return new Promise((res, rej) => {
      const rq = indexedDB.open("cp_images", 1);
      rq.onupgradeneeded = () => rq.result.createObjectStore("img");
      rq.onsuccess = () => { this._db = rq.result; res(this._db); };
      rq.onerror = () => rej(rq.error);
    });
  },
  async set(k, v) { const db = await this.open(); return new Promise((res) => { const t = db.transaction("img", "readwrite"); t.objectStore("img").put(v, k); t.oncomplete = res; }); },
  async get(k) { const db = await this.open(); return new Promise((res) => { const t = db.transaction("img", "readonly"); const r = t.objectStore("img").get(k); r.onsuccess = () => res(r.result); }); },
  async del(k) { const db = await this.open(); return new Promise((res) => { const t = db.transaction("img", "readwrite"); t.objectStore("img").delete(k); t.oncomplete = res; }); },
  async all() { const db = await this.open(); return new Promise((res) => { const out = {}; const t = db.transaction("img", "readonly"); const s = t.objectStore("img"); const c = s.openCursor(); c.onsuccess = (e) => { const cur = e.target.result; if (cur) { out[cur.key] = cur.value; cur.continue(); } else res(out); }; }); },
};

/* ---------- ids ---------- */
const COVERS = ["#c8a878", "#8aa6a3", "#c99f98", "#9aa6c0", "#bfae8a", "#a8a394"];
let _sid = 7;
const nextId = (p) => p + "_" + (Date.now().toString(36)) + "_" + (_sid++).toString(36) + Math.floor(Math.random() * 1e4).toString(36);

// Bắt đầu rỗng — không còn dữ liệu mockup. Dữ liệu thật đến từ Supabase (chế độ cấu hình)
// hoặc do người dùng tự tạo (chế độ demo localStorage).
function buildSeed() {
  return { projects: [], photos: [], savedAt: Date.now() };
}

/* URL ảnh thu nhỏ qua Cloudflare Image Resizing (cdn-cgi/image) cho lưới ảnh.
   Album lớn: tải bản ~vài chục KB thay vì ảnh gốc nhiều MB. Tự fallback nếu tắt/không hỗ trợ. */
function cpResizeUrl(url, w) {
  try {
    const cfg = window.__CP_CONFIG__ || {};
    if (cfg.IMG_RESIZE === false || !url || !/^https?:\/\//.test(url)) return url;
    const u = new URL(url);
    if (u.pathname.indexOf("/cdn-cgi/") === 0) return url; // tránh lồng
    return u.origin + "/cdn-cgi/image/width=" + (w || 480) + ",quality=72,format=auto" + u.pathname;
  } catch (e) { return url; }
}
window.cpResizeUrl = cpResizeUrl;

/* Đặt tên hiển thị không trùng trong cùng project: "IMG.jpg" → "IMG (2).jpg". */
function uniqueName(name, taken) {
  let cand = name;
  if (taken.has(cand)) {
    const dot = name.lastIndexOf(".");
    const base = dot > 0 ? name.slice(0, dot) : name;
    const ext = dot > 0 ? name.slice(dot) : "";
    let i = 2;
    do { cand = base + " (" + i + ")" + ext; i++; } while (taken.has(cand));
  }
  taken.add(cand);
  return cand;
}

/* ---------- store hook ---------- */
function useStore() {
  // Có cấu hình Supabase → dùng store thật (R2 + Postgres). Chưa → prototype localStorage.
  // cpConfigured() không đổi trong suốt phiên nên nhánh hook ổn định.
  if (window.cpConfigured && window.cpConfigured()) return useRemoteStore();
  return useLocalStore();
}

function useLocalStore() {
  const [data, setData] = React.useState(() => {
    // migrate older saves: retire "edit" status, backfill access code + guests
    const fix = (d) => ({
      ...d,
      projects: d.projects.map((p) => ({
        ...p,
        guests: p.guests || [],
        code: p.code || (((p.name || "").replace(/[^a-zA-Z]/g, "").toUpperCase().slice(0, 6)) || "ALBUM") + "26",
      })),
      photos: d.photos.map((p) => p.status === "edit" ? { ...p, status: "pick" } : p),
    });
    try { const raw = localStorage.getItem(LS_KEY); if (raw) return fix(JSON.parse(raw)); } catch (e) {}
    return buildSeed();
  });
  const [images, setImages] = React.useState({}); // id -> dataURL (uploads)

  // load uploaded images from idb
  React.useEffect(() => { idb.all().then(setImages).catch(() => {}); }, []);

  // persist metadata (strip nothing — images live in idb)
  React.useEffect(() => {
    try { localStorage.setItem(LS_KEY, JSON.stringify(data)); } catch (e) {}
  }, [data]);

  const patchPhoto = React.useCallback((id, patch) => {
    setData((d) => ({ ...d, photos: d.photos.map((p) => p.id === id ? { ...p, ...(typeof patch === "function" ? patch(p) : patch) } : p) }));
  }, []);

  const api = React.useMemo(() => ({
    // resolve display src
    src(photo) {
      if (!photo) return "";
      if (photo.url) return photo.url;                 // ảnh thật trên R2 (public_url)
      if (photo.upload) return images[photo.id] || ""; // ảnh upload offline (IndexedDB)
      return window.makePhoto(photo.seed, photo.w, photo.h);
    },
    // bản nhỏ cho lưới/thumbnail (album lớn tải nhẹ hơn nhiều)
    thumb(photo, w) {
      if (!photo) return "";
      if (photo.url) return cpResizeUrl(photo.url, w || 480);
      return this.src(photo);
    },
    project(id) { return data.projects.find((p) => p.id === id); },
    projectPhotos(id) { return data.photos.filter((p) => p.projectId === id); },

    addProject({ name, couple, date, cover }) {
      const pid = nextId("pr");
      const albums = [{ id: nextId("al"), name: "Tất cả ảnh" }];
      const code = ((name || "").replace(/[^a-zA-Z]/g, "").toUpperCase().slice(0, 6) || "ALBUM") + Math.floor(10 + Math.random() * 89);
      setData((d) => ({ ...d, projects: [{ id: pid, name, couple, date, cover, albums, code, guests: [], createdAt: Date.now() }, ...d.projects] }));
      return pid;
    },
    projectByCode(code) {
      const c = (code || "").trim().toUpperCase();
      if (!c) return null;
      return data.projects.find((p) => (p.code || "").toUpperCase() === c) || null;
    },
    addGuest(projectId, guest) {
      setData((d) => ({ ...d, projects: d.projects.map((p) => p.id === projectId ? { ...p, guests: [...(p.guests || []), guest] } : p) }));
    },
    removeGuest(projectId, email) {
      setData((d) => ({ ...d, projects: d.projects.map((p) => p.id === projectId ? { ...p, guests: (p.guests || []).filter((g) => g.email !== email) } : p) }));
    },
    addAlbum(projectId, name) {
      const al = { id: nextId("al"), name };
      setData((d) => ({ ...d, projects: d.projects.map((p) => p.id === projectId ? { ...p, albums: [...p.albums, al] } : p) }));
      return al.id;
    },
    async addUploads(projectId, albumId, files, onProgress) {
      // Chế độ demo (chưa cấu hình Supabase): bytes lưu IndexedDB. Khi đã cấu hình,
      // useStore() đã định tuyến sang useRemoteStore (upload R2), không vào đây.
      const taken = new Set(data.photos.filter((p) => p.projectId === projectId).map((p) => p.filename));
      const newPhotos = [];
      let done = 0;
      for (const file of files) {
        const id = nextId("ph");
        const dims = await fileImgDims(file);
        const dataUrl = await readFileAsDataURL(file);
        await idb.set(id, dataUrl);
        setImages((m) => ({ ...m, [id]: dataUrl }));
        newPhotos.push({
          id, projectId, albumId, upload: true, filename: uniqueName(file.name, taken),
          w: dims.w, h: dims.h, stars: 0, liked: false, status: "none", note: "", comments: [],
        });
        done++; onProgress && onProgress(done, files.length, file.name);
      }
      setData((d) => ({ ...d, photos: [...newPhotos, ...d.photos] }));
      return newPhotos.length;
    },
    setStars(id, n) { patchPhoto(id, (p) => ({ stars: p.stars === n ? 0 : n })); },
    toggleLike(id) { patchPhoto(id, (p) => ({ liked: !p.liked })); },
    setStatus(id, s) { patchPhoto(id, (p) => ({ status: p.status === s ? "none" : s })); },
    setNote(id, note) { patchPhoto(id, { note }); },
    addComment(id, comment) { patchPhoto(id, (p) => ({ comments: [...(p.comments || []), comment] })); },
    moveToAlbum(id, albumId) { patchPhoto(id, { albumId }); },
    deletePhoto(id) {
      // prototype: xoá khỏi state + IndexedDB. Bản production: db.deletePhoto(id)
      // → trigger AFTER DELETE tự xoá object trên R2 (supabase/02_r2_delete_trigger.sql).
      idb.del && idb.del(id);
      setData((d) => ({ ...d, photos: d.photos.filter((p) => p.id !== id) }));
    },
    resetAll() { if (confirm("Khôi phục dữ liệu mẫu? Mọi thay đổi sẽ mất.")) { localStorage.removeItem(LS_KEY); setData(buildSeed()); } },
    _data: data,
  }), [data, images, patchPhoto]);

  return api;
}

function readFileAsDataURL(file) {
  return new Promise((res, rej) => { const r = new FileReader(); r.onload = () => res(r.result); r.onerror = rej; r.readAsDataURL(file); });
}
function imgDims(url) {
  return new Promise((res) => { const im = new Image(); im.onload = () => res({ w: im.naturalWidth, h: im.naturalHeight }); im.onerror = () => res({ w: 600, h: 600 }); im.src = url; });
}
function fileImgDims(file) {
  return new Promise((res) => {
    const url = URL.createObjectURL(file);
    const im = new Image();
    im.onload = () => { res({ w: im.naturalWidth, h: im.naturalHeight }); URL.revokeObjectURL(url); };
    im.onerror = () => { res({ w: 600, h: 600 }); URL.revokeObjectURL(url); };
    im.src = url;
  });
}

window.useStore = useStore;
