// generator-app.jsx — sidebar + form + live preview + PNG export

const { useState, useMemo, useRef } = React;
const TPLS = window.LIROU_TEMPLATES;

function showToast(msg) {
  const t = document.getElementById("toast");
  t.textContent = msg;
  t.classList.add("show");
  clearTimeout(window.__lirouToastT);
  window.__lirouToastT = setTimeout(() => t.classList.remove("show"), 2200);
}

function loadState() {
  try { return JSON.parse(localStorage.getItem("lirou-gen") || "{}"); } catch { return {}; }
}
function saveState(s) {
  // strip image data URLs (too big for localStorage; user re-uploads on reload)
  const cleaned = { activeId: s.activeId, data: {} };
  for (const [id, fields] of Object.entries(s.data || {})) {
    cleaned.data[id] = { ...fields };
    if (cleaned.data[id].image && cleaned.data[id].image.startsWith("data:")) {
      cleaned.data[id].image = "";
    }
  }
  try { localStorage.setItem("lirou-gen", JSON.stringify(cleaned)); } catch {}
}

function App() {
  const initial = loadState();
  const [activeId, setActiveId] = useState(initial.activeId || TPLS[0].id);
  const [allData, setAllData] = useState(() => {
    const d = {};
    TPLS.forEach(t => { d[t.id] = { ...t.defaults, ...(initial.data && initial.data[t.id] || {}) }; });
    return d;
  });

  const tpl = useMemo(() => TPLS.find(t => t.id === activeId), [activeId]);
  const data = allData[activeId];
  const previewRef = useRef(null);

  function updateField(k, v) {
    setAllData(prev => {
      const next = { ...prev, [activeId]: { ...prev[activeId], [k]: v } };
      saveState({ activeId, data: next });
      return next;
    });
  }
  function selectTpl(id) {
    setActiveId(id);
    saveState({ activeId: id, data: allData });
  }
  function resetTpl() {
    setAllData(prev => {
      const next = { ...prev, [activeId]: { ...tpl.defaults } };
      saveState({ activeId, data: next });
      return next;
    });
  }

  async function exportPng() {
    if (!previewRef.current) return;
    showToast("renderizando…");
    try {
      const node = previewRef.current.querySelector(".tpl-canvas");
      // export at native size — clear scale transform so the PNG matches tpl.w × tpl.h exactly,
      // sem espaço em volta (o problema do "espaço grande" no preview do mac vinha do scale CSS).
      const prevTransform = node.style.transform;
      node.style.transform = "none";
      const dataUrl = await window.htmlToImage.toPng(node, {
        width: tpl.w, height: tpl.h, canvasWidth: tpl.w, canvasHeight: tpl.h,
        pixelRatio: 3, cacheBust: true,
        style: { transform: "none", margin: "0", padding: "0" }
      });
      node.style.transform = prevTransform;
      const a = document.createElement("a");
      a.download = `lirou-${tpl.id}-${Date.now()}.png`;
      a.href = dataUrl;
      a.click();
      showToast("imagem baixada ✦");
    } catch (e) {
      console.error(e);
      showToast("erro ao exportar :(");
    }
  }

  // Group sidebar
  const groups = useMemo(() => {
    const g = {};
    TPLS.forEach(t => { g[t.group] = g[t.group] || []; g[t.group].push(t); });
    return g;
  }, []);

  return (
    <>
      {/* SIDEBAR */}
      {ReactDOM.createPortal(
        <>
          <div className="brand">
            <div className="name">Lirou Closet 65</div>
            <div className="meta">gerador · v0.1</div>
          </div>
          {Object.entries(groups).map(([groupName, items]) => (
            <div key={groupName}>
              <div className="group">{groupName}</div>
              {items.map(t => (
                <div key={t.id} className={"nav-item" + (activeId === t.id ? " active" : "")} onClick={() => selectTpl(t.id)}>
                  <span className="dot" />
                  <span>{t.name}</span>
                </div>
              ))}
            </div>
          ))}
        </>, document.getElementById("nav"))}

      {/* FORM */}
      {ReactDOM.createPortal(
        <>
          <h2>{tpl.name}</h2>
          <p className="lede">{tpl.w} × {tpl.h} · edita aqui, exporta na direita</p>
          {tpl.fields.map(f => (
            <div key={f.k} className="field">
              <label>{f.label}</label>
              {f.type === "textarea" ? (
                <textarea value={data[f.k]} onChange={e => updateField(f.k, e.target.value)} rows={f.k === "rows" ? 6 : 3} />
              ) : f.type === "color" ? (
                <div>
                  <div className="swatches">
                    {f.options.map(c => (
                      <div key={c} className={"swatch-btn" + (data[f.k] === c ? " active" : "")} style={{ background: c, borderColor: data[f.k] === c ? "#1b1b1a" : (c === "#ffffff" ? "#e3ddd0" : "transparent") }} onClick={() => updateField(f.k, c)} title={c} />
                    ))}
                    <label style={{ width: 28, height: 28, borderRadius: 999, border: "1.5px dashed #c8c0ad", display: "inline-flex", alignItems: "center", justifyContent: "center", cursor: "pointer", fontSize: 14, color: "#888", background: "#fafaf7", position: "relative", overflow: "hidden" }} title="cor personalizada">
                      <span style={{ position: "relative", zIndex: 1, pointerEvents: "none" }}>+</span>
                      <input type="color" value={data[f.k] || "#674689"} onChange={e => updateField(f.k, e.target.value)} style={{ position: "absolute", inset: 0, opacity: 0, cursor: "pointer" }} />
                    </label>
                  </div>
                  <div className="hint" style={{ marginTop: 6, fontFamily: "'JetBrains Mono', monospace", fontSize: 10, color: "#aaa" }}>{(data[f.k] || "").toUpperCase()}</div>
                </div>
              ) : f.type === "image" ? (
                <ImageField value={data[f.k]} onChange={v => updateField(f.k, v)} />
              ) : (
                <input type="text" value={data[f.k]} onChange={e => updateField(f.k, e.target.value)} />
              )}
              {f.hint && <div className="hint">{f.hint}</div>}
            </div>
          ))}
          <div className="actions">
            <button className="btn btn-primary" onClick={exportPng}>baixar PNG ↓</button>
            <button className="btn btn-ghost" onClick={resetTpl}>resetar campos</button>
          </div>
        </>, document.getElementById("form"))}

      {/* PREVIEW */}
      {ReactDOM.createPortal(
        <>
          <div className="preview-header">
            <div className="preview-title">preview</div>
            <div className="preview-meta">{tpl.w}×{tpl.h}px</div>
          </div>
          <div className="canvas-wrap" ref={previewRef}>
            <PreviewCanvas tpl={tpl} data={data} />
          </div>
          <div style={{ fontSize: 11, color: "#999", maxWidth: 540, textAlign: "center", lineHeight: 1.5 }}>
            ✦ as alterações são salvas automaticamente neste navegador. clique em <b>baixar PNG</b> pra exportar em tamanho real.
          </div>
        </>, document.getElementById("preview"))}
    </>
  );
}

function ImageField({ value, onChange }) {
  const inputRef = useRef(null);
  function handleFile(file) {
    if (!file) return;
    const reader = new FileReader();
    reader.onload = e => onChange(e.target.result);
    reader.readAsDataURL(file);
  }
  return (
    <div>
      <input ref={inputRef} type="file" accept="image/*" style={{ display: "none" }} onChange={e => handleFile(e.target.files[0])} />
      {value ? (
        <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
          <div style={{ width: 64, height: 64, borderRadius: 8, overflow: "hidden", background: "#fafaf7", border: "1px solid #e3ddd0", flex: "none" }}>
            <img src={value} style={{ width: "100%", height: "100%", objectFit: "cover", display: "block" }} />
          </div>
          <div style={{ display: "flex", flexDirection: "column", gap: 6, flex: 1 }}>
            <button type="button" className="btn btn-ghost" style={{ padding: "8px 14px", fontSize: 11 }} onClick={() => inputRef.current?.click()}>trocar imagem</button>
            <button type="button" className="btn" style={{ padding: "8px 14px", fontSize: 11, background: "transparent", color: "#999", border: "1px solid #e3ddd0" }} onClick={() => onChange("")}>remover</button>
          </div>
        </div>
      ) : (
        <div onClick={() => inputRef.current?.click()} onDragOver={e => { e.preventDefault(); }} onDrop={e => { e.preventDefault(); handleFile(e.dataTransfer.files[0]); }} style={{ padding: "24px 16px", border: "1.5px dashed #c8c0ad", borderRadius: 8, textAlign: "center", cursor: "pointer", background: "#fafaf7", color: "#888", fontSize: 12, lineHeight: 1.5 }}>
          <div style={{ fontSize: 24, marginBottom: 4 }}>↑</div>
          clique ou arraste uma foto<br/><span style={{ color: "#bbb", fontSize: 11 }}>jpg, png, webp</span>
        </div>
      )}
    </div>
  );
}

function PreviewCanvas({ tpl, data }) {
  // adaptive scale: fit within max box (portrait, square, landscape all OK)
  const maxW = 540, maxH = 760;
  const scale = Math.min(maxW / tpl.w, maxH / tpl.h);
  const dW = tpl.w * scale, dH = tpl.h * scale;
  return (
    <div style={{ width: dW, height: dH, position: "relative", overflow: "hidden", borderRadius: 10 }}>
      <div className="tpl-canvas" style={{ width: tpl.w, height: tpl.h, transform: `scale(${scale})`, transformOrigin: "top left", position: "absolute", top: 0, left: 0 }}>
        {tpl.render(data)}
      </div>
    </div>
  );
}

ReactDOM.createRoot(document.body.appendChild(document.createElement("div"))).render(<App />);
