/* ============================================================
   3DAX — Admin · Listings manager (CRUD + photo upload)
   ============================================================ */

/* Empty / migration state shown when Firestore collections are empty.
   Lets the admin trigger the initial migration and surfaces real errors. */
function AdminMigrate({ what }){
  const [busy, setBusy] = useState(false);
  const [msg, setMsg] = useState(null);
  const canSeed = window.Store && Store.seedNow;
  const lastErr = window.Store && Store.lastError && Store.lastError();

  const run = async () => {
    if(!canSeed) return;
    setBusy(true); setMsg(null);
    const r = await Store.seedNow();
    setBusy(false);
    setMsg(r.ok ? { ok:true, t:"✓ Migración completada. Cargando…" } : { ok:false, t:"Error: " + r.error });
  };

  return (
    <div className="adm__empty">
      <div className="adm__empty-ic">◳</div>
      <h3 className="display">No hay {what} todavía</h3>
      {canSeed ? (
        <>
          <p>Tu base de datos de Firebase está vacía. Pulsa para migrar el catálogo y las
          reseñas iniciales a Firestore (solo hace falta una vez).</p>
          {(lastErr || (msg && !msg.ok)) && (
            <div className="adm__empty-err">
              <strong>No se pudo migrar.</strong> {msg ? msg.t.replace("Error: ","") : lastErr}
              <div className="adm__empty-hint">Comprueba en Firebase Console que: 1) publicaste las
              reglas de <code>firestore.rules</code>, 2) entraste con <code>adricm427@gmail.com</code>.</div>
            </div>
          )}
          {msg && msg.ok && <div className="adm__empty-ok">{msg.t}</div>}
          <button className="btn btn-primary btn-lg" onClick={run} disabled={busy}>
            {busy ? <span className="spin" /> : "Migrar catálogo inicial"}
          </button>
        </>
      ) : (
        <p>Crea tu primer listing con el botón “+ Nuevo listing”.</p>
      )}
    </div>
  );
}

function AdminListings({ products }){
  const [editing, setEditing] = useState(null); // product object or {} for new
  const [confirm, setConfirm] = useState(null);

  useEffect(() => {
    const onNew = () => setEditing({ _new: true });
    window.addEventListener("adm:new", onNew);
    return () => window.removeEventListener("adm:new", onNew);
  }, []);

  const sorted = [...products].sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
  const isFirebase = window.Store && Store._firebase;

  return (
    <div className="adm__view">
      {sorted.length === 0 && isFirebase ? <AdminMigrate what="listings" /> : (
      <div className="adm__table">
        <div className="adm__thead">
          <span>Producto</span><span>Franquicia</span><span>Precio</span><span>Stock</span><span>Estado</span><span></span>
        </div>
        {sorted.map((p) => (
          <div className="adm__trow" key={p.id}>
            <div className="adm__prod">
              <div className="adm__thumb">
                {p.images && p.images[0]
                  ? <img src={p.images[0]} alt="" />
                  : <div className="adm__thumb-ph">◳</div>}
              </div>
              <div><div className="adm__pname">{p.name}</div><div className="adm__pchar">{p.char}</div></div>
            </div>
            <span className="adm__muted">{p.franchise}</span>
            <span>{eur(p.price)}</span>
            <span className={p.stock === 0 ? "adm__danger" : ""}>{p.stock} uds</span>
            <span className="adm__states">
              {p.featured && <span className="adm__tag is-feat">Destacado</span>}
              <span className={"adm__tag " + (p.available ? "is-done" : "")}>{p.available ? "Visible" : "Oculto"}</span>
            </span>
            <span className="adm__actions">
              <button onClick={() => setEditing(p)} title="Editar">✎</button>
              <button onClick={() => setConfirm(p)} title="Borrar" className="adm__del">🗑</button>
            </span>
          </div>
        ))}
      </div>
      )}

      {editing && <ListingEditor product={editing} onClose={() => setEditing(null)} />}
      {confirm && (
        <div className="auth" role="dialog">
          <div className="auth__scrim" onClick={() => setConfirm(null)} />
          <div className="auth__panel adm__confirm">
            <h3 className="display">¿Borrar “{confirm.name}”?</h3>
            <p className="auth__sub">Esta acción no se puede deshacer.</p>
            <div className="adm__confirm-btns">
              <button className="btn btn-ghost" onClick={() => setConfirm(null)}>Cancelar</button>
              <button className="btn btn-primary" onClick={async () => { await Store.deleteProduct(confirm.id); setConfirm(null); }}>Borrar</button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

function ListingEditor({ product, onClose }){
  const isNew = !!product._new;
  const [f, setF] = useState(() => ({
    id: product.id, char: product.char || "", name: product.name || "",
    franchise: product.franchise || "One Piece TCG", price: product.price ?? 50,
    stock: product.stock ?? 10, available: product.available !== false, featured: !!product.featured,
    tag: product.tag || "One Piece TCG", blurb: product.blurb || "",
    colorways: (product.colorways && product.colorways.length ? product.colorways : [{ name: "Cyan / Sakura", from: "#34e0d4", to: "#ff4fa3" }]).map((c) => ({ ...c })),
  }));
  // images: {url, ref?(existing), blob?(new)}
  const [imgs, setImgs] = useState(() => (product.images || []).map((url, i) => ({ url, ref: (product.imageRefs || [])[i] })));
  const [cut, setCut] = useState(true);
  const [busy, setBusy] = useState(false);
  const [drag, setDrag] = useState(false);
  const fileRef = useRef(null);
  // modelo 3D: URLs existentes + blobs nuevos por pieza
  const [model, setModel] = useState(() => (product.model && typeof product.model === "object") ? { ...product.model } : null);
  const [glb, setGlb] = useState({ base:null, body:null, lid:null });   // File nuevos
  const glbRefs = { base: useRef(null), body: useRef(null), lid: useRef(null) };

  useEffect(() => { document.body.style.overflow = "hidden"; return () => { document.body.style.overflow = ""; }; }, []);

  const set = (k) => (e) => setF((s) => ({ ...s, [k]: e.target.type === "checkbox" ? e.target.checked : e.target.value }));

  const [genBusy, setGenBusy] = useState(false);
  // genera el preview 3D (GTAO + fondo transparente) en un iframe oculto y lo añade como foto principal
  const genPreview = () => {
    setGenBusy(true);
    const ifr = document.createElement("iframe");
    ifr.style.cssText = "position:fixed;left:-9999px;top:0;width:900px;height:600px;border:0;";
    ifr.src = "experiencia-3d.html?id=" + encodeURIComponent(f.id || "yamato") + "&thumb=1";
    document.body.appendChild(ifr);
    let tries = 0, settle = 0;
    const poll = setInterval(async () => {
      tries++;
      let win = null; try { win = ifr.contentWindow; } catch (e) {}
      const ready = win && win.__deckH && typeof win.captureThumb === "function";
      if (ready) settle++;
      if (ready && settle >= 6) {            // espera a que el GTAO se asiente
        clearInterval(poll);
        try {
          const url = win.captureThumb();
          // downscale a ~420px comprimido → ligero para guardar en Firestore (sin Storage ni repo)
          const small = await new Promise((res2) => {
            const im = new Image();
            im.onload = () => { const S=1024; const c=document.createElement("canvas"); c.width=S;c.height=S;
              const x=c.getContext("2d"); x.imageSmoothingEnabled=true; x.imageSmoothingQuality="high"; x.drawImage(im,0,0,S,S);
              res2(c.toDataURL("image/png")); };
            im.onerror = () => res2(url); im.src = url;
          });
          // guarda el data URL como imagen principal del listing → aparece al instante en tienda/index/colecciones
          setImgs((arr) => [{ url: small, ref: small }, ...arr.filter(x => x.ref !== small)]);
        } catch (e) { alert("No se pudo generar el preview: " + e.message); }
        document.body.removeChild(ifr); setGenBusy(false);
      } else if (tries > 50) {
        clearInterval(poll); try { document.body.removeChild(ifr); } catch (e) {}
        setGenBusy(false); alert("Tiempo agotado generando el preview 3D.");
      }
    }, 400);
  };

  const addFiles = async (files) => {
    setBusy(true);
    for (const file of files) {
      if(!file.type.startsWith("image/")) continue;
      try {
        const r = await window.ImgProc.process(file, { cutout: cut, maxSide: 800 });
        setImgs((arr) => [...arr, { url: r.dataURL, blob: r.blob }]);
      } catch (e) { /* skip */ }
    }
    setBusy(false);
  };
  const onDrop = (e) => { e.preventDefault(); setDrag(false); addFiles([...e.dataTransfer.files]); };
  const removeImg = (i) => setImgs((arr) => arr.filter((_, j) => j !== i));

  const cw = (i, k, v) => setF((s) => ({ ...s, colorways: s.colorways.map((c, j) => j === i ? { ...c, [k]: v } : c) }));
  const addCw = () => setF((s) => ({ ...s, colorways: [...s.colorways, { name: "Nuevo", from: "#822614", to: "#f0489a" }] }));
  const rmCw = (i) => setF((s) => ({ ...s, colorways: s.colorways.filter((_, j) => j !== i) }));

  const save = async () => {
    setBusy(true);
    const newBlobs = imgs.filter((x) => x.blob).map((x) => x.blob);
    const keptRefs = imgs.filter((x) => x.ref || x.repoPath).map((x) => x.repoPath || x.ref);
    const glbBlobs = { base: glb.base || null, body: glb.body || null, lid: glb.lid || null };
    await Store.saveProduct({ ...f, price: +f.price, stock: +f.stock, imageRefs: keptRefs, model }, newBlobs, glbBlobs);
    setBusy(false);
    onClose();
  };

  const setGlbPart = (part) => (e) => {
    const file = e.target.files && e.target.files[0];
    if(file) setGlb((s) => ({ ...s, [part]: file }));
  };
  const clearGlbPart = (part) => {
    setGlb((s) => ({ ...s, [part]: null }));
    setModel((m) => { if(!m) return m; const n = { ...m }; delete n[part]; return Object.keys(n).length ? n : null; });
  };
  const glbState = (part) => glb[part] ? glb[part].name : (model && model[part] ? "Guardado ✓" : null);

  return (
    <div className="ledit" role="dialog" aria-modal="true">
      <div className="ledit__scrim" onClick={onClose} />
      <div className="ledit__panel">
        <div className="ledit__bar">
          <h2 className="display">{isNew ? "Nuevo listing" : "Editar listing"}</h2>
          <button className="co__close" onClick={onClose} aria-label="Cerrar">
            <svg width="20" height="20" viewBox="0 0 24 24" stroke="currentColor" strokeWidth="1.6"><path d="M6 6l12 12M18 6L6 18"/></svg>
          </button>
        </div>

        <div className="ledit__body">
          {/* image upload */}
          <div className="ledit__sect">
            <div className="ledit__label">Fotos del producto</div>
            <div className={"uploader" + (drag ? " is-drag" : "")}
                 onDragOver={(e) => { e.preventDefault(); setDrag(true); }}
                 onDragLeave={() => setDrag(false)} onDrop={onDrop}
                 onClick={() => fileRef.current.click()}>
              <input ref={fileRef} type="file" accept="image/*" multiple hidden
                     onChange={(e) => addFiles([...e.target.files])} />
              <div className="uploader__ic">⬆</div>
              <div className="uploader__t">Arrastra fotos o haz clic para subir</div>
              <div className="uploader__s">{busy ? "Procesando…" : "PNG/JPG · se recorta y optimiza solo"}</div>
            </div>
            <label className="uploader__cut">
              <input type="checkbox" checked={cut} onChange={(e) => setCut(e.target.checked)} />
              Recortar fondo automáticamente al subir
            </label>
            {imgs.length > 0 && (
              <div className="ledit__imgs">
                {imgs.map((im, i) => (
                  <div className="ledit__img" key={i}>
                    <img src={im.url} alt="" />
                    <button onClick={() => removeImg(i)} aria-label="Quitar">×</button>
                    {i === 0 && <span className="ledit__main">principal</span>}
                  </div>
                ))}
              </div>
            )}
          </div>

          {/* fields */}
          <div className="ledit__grid">
            <label className="field"><span className="field__label">Personaje</span>
              <input value={f.char} onChange={set("char")} placeholder="Tony Tony Chopper" /></label>
            <label className="field"><span className="field__label">Nombre del listing</span>
              <input value={f.name} onChange={set("name")} placeholder="Chopper · Wanted" /></label>
            <label className="field"><span className="field__label">Franquicia</span>
              <select value={f.franchise} onChange={set("franchise")}>
                <option>One Piece TCG</option><option>Riftbound</option><option>Magic: The Gathering</option>
                <option>Dragon Ball Super</option><option>Flesh and Blood</option><option>Final Fantasy TCG</option>
              </select></label>
            <label className="field"><span className="field__label">Etiqueta</span>
              <input value={f.tag} onChange={set("tag")} placeholder="One Piece TCG" /></label>
            <label className="field"><span className="field__label">Precio (€)</span>
              <input type="number" value={f.price} onChange={set("price")} /></label>
            <label className="field"><span className="field__label">Stock (uds)</span>
              <input type="number" value={f.stock} onChange={set("stock")} /></label>
          </div>

          <label className="field"><span className="field__label">Descripción</span>
            <textarea value={f.blurb} onChange={set("blurb")} rows="3" placeholder="Describe el relieve, capacidad, detalles…" /></label>

          {/* colorways */}
          <div className="ledit__sect">
            <div className="ledit__label">Acabados / colores</div>
            {f.colorways.map((c, i) => (
              <div className="cwrow" key={i}>
                <span className="cwrow__sw" style={{ background:`linear-gradient(135deg, ${c.from}, ${c.to})` }} />
                <input value={c.name} onChange={(e) => cw(i, "name", e.target.value)} placeholder="Nombre" />
                <input type="color" value={c.from} onChange={(e) => cw(i, "from", e.target.value)} />
                <input type="color" value={c.to} onChange={(e) => cw(i, "to", e.target.value)} />
                <button onClick={() => rmCw(i)} className="cwrow__rm" aria-label="Quitar">×</button>
              </div>
            ))}
            <button className="ledit__addcw" onClick={addCw}>+ Añadir acabado</button>
          </div>

          {/* modelo 3D (GLB) */}
          <div className="ledit__sect">
            <div className="ledit__label">Modelo 3D · GLB <span style={{ fontWeight:400, textTransform:"none", letterSpacing:0, color:"var(--cream-faint)" }}>(opcional · tapa, caja y base por separado, mismo origen)</span></div>
            <div className="glbgrid">
              {[["lid","Tapa"],["body","Caja"],["base","Base"]].map(([part,label]) => (
                <div className="glbslot" key={part}>
                  <input ref={glbRefs[part]} type="file" accept=".glb,model/gltf-binary" hidden onChange={setGlbPart(part)} />
                  <button className={"glbslot__drop" + (glbState(part) ? " has" : "")} onClick={() => glbRefs[part].current.click()}>
                    <span className="glbslot__ic">◧</span>
                    <span className="glbslot__label">{label}</span>
                    <span className="glbslot__state">{glbState(part) || "subir .glb"}</span>
                  </button>
                  {glbState(part) && <button className="glbslot__rm" onClick={() => clearGlbPart(part)} aria-label="Quitar">×</button>}
                </div>
              ))}
            </div>
            <div className="glbhint">Si subes modelo 3D, la ficha mostrará la caja interactiva (girar + abrir tapa). Sin GLB, se usa la foto. Recomendado &lt;3MB por pieza (comprimido Draco/Meshopt).</div>
            {(glbState("lid") && glbState("body") && glbState("base")) && (
              <div className="ledit__previewgen">
                <button className="btn btn-gold" onClick={genPreview} disabled={genBusy}>
                  {genBusy ? "Generando preview 3D…" : "✨ Generar foto 3D y usarla"}
                </button>
                <span className="glbhint">Genera la foto 3/4 con GTAO y la guarda como imagen del listing. Pulsa <b>Guardar</b> y aparece en tienda, index y colecciones.</span>
              </div>
            )}
          </div>

          {/* toggles */}
          <div className="ledit__toggles">
            <label className="tgl"><input type="checkbox" checked={f.available} onChange={set("available")} /> <span>Visible en la tienda</span></label>
            <label className="tgl"><input type="checkbox" checked={f.featured} onChange={set("featured")} /> <span>Marcar como destacado</span></label>
          </div>
        </div>

        <div className="ledit__foot">
          <button className="btn btn-ghost" onClick={onClose}>Cancelar</button>
          <button className="btn btn-primary btn-lg" onClick={save} disabled={busy}>
            {busy ? <span className="spin" /> : (isNew ? "Crear listing" : "Guardar cambios")}
          </button>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { AdminListings, ListingEditor, AdminMigrate });
