/* Poster preview: artwork renderer + frame wrapper + room scene */
const { PS_DATA } = window;
const { useRef: useRefPv, useEffect: useEffectPv } = React;

function bgHex(id) {
  const c = PS_DATA.BG_COLORS.find(b => b.id === id);
  return c ? c.hex : "#ECE2D0";
}
function fontCss(id) {
  const f = PS_DATA.POSTER_FONTS.find(x => x.id === id);
  return f ? f.css : '"Newsreader", serif';
}

/* ---- Inline-editable text (uncontrolled contentEditable so the caret never jumps) ---- */
function EditableText({ value, field, update, multiline, style }) {
  const ref = useRefPv(null);
  useEffectPv(() => {
    const el = ref.current;
    if (el && document.activeElement !== el && el.innerText !== (value || "")) el.innerText = value || "";
  }, [value]);
  return (
    <div
      ref={ref}
      className="pe-edit"
      contentEditable
      suppressContentEditableWarning
      spellCheck={false}
      onInput={e => update && update({ [field]: e.currentTarget.innerText })}
      onKeyDown={multiline ? undefined : e => { if (e.key === "Enter") { e.preventDefault(); e.currentTarget.blur(); } }}
      onPointerDown={e => e.stopPropagation()}
      onPointerMove={e => e.stopPropagation()}
      style={{ outline: "none", cursor: "text", ...style }}
    />
  );
}
/* render editable when in edit mode, otherwise a plain div */
function Txt({ edit, update, value, field, multiline, style }) {
  if (edit && update) return <EditableText value={value} field={field} update={update} multiline={multiline} style={style} />;
  return <div style={style}>{value}</div>;
}

/* ---- Individual template artworks (sized in container query units) ---- */
function ArtQuote({ d, ink, edit, update }) {
  return (
    <div style={{ height: "100%", display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", textAlign: "center", padding: "12cqw 9cqw" }}>
      <div style={{ width: "9cqw", height: ".5cqw", background: ink, opacity: .5, marginBottom: "7cqh" }} />
      <Txt edit={edit} update={update} value={d.headline} field="headline" multiline style={{ fontFamily: fontCss(d.font), color: ink, fontSize: "13cqw", lineHeight: 1.04, fontWeight: 500, whiteSpace: "pre-line", letterSpacing: "-.01em" }} />
      <Txt edit={edit} update={update} value={d.subline} field="subline" style={{ fontFamily: 'var(--poster-sans)', color: ink, opacity: .72, fontSize: "3.1cqw", letterSpacing: ".34em", marginTop: "7cqh", fontWeight: 600 }} />
    </div>
  );
}
function ArtName({ d, ink, edit, update }) {
  return (
    <div style={{ height: "100%", display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", textAlign: "center", padding: "11cqw 8cqw" }}>
      <div style={{ width: "26cqw", height: ".5cqw", background: ink, opacity: .55 }} />
      <Txt edit={edit} update={update} value={d.headline} field="headline" multiline style={{ fontFamily: fontCss(d.font), color: ink, fontSize: "10.5cqw", lineHeight: 1.04, fontWeight: 600, whiteSpace: "pre-line", letterSpacing: "0", margin: "5cqh 0", maxWidth: "100%" }} />
      <Txt edit={edit} update={update} value={d.subline} field="subline" style={{ fontFamily: 'var(--poster-sans)', color: ink, opacity: .8, fontSize: "3.4cqw", letterSpacing: ".4em", fontWeight: 700 }} />
      <div style={{ width: "26cqw", height: ".5cqw", background: ink, opacity: .55, marginTop: "5cqh" }} />
      {(d.meta || edit) && <Txt edit={edit} update={update} value={d.meta} field="meta" style={{ fontFamily: 'var(--poster-sans)', color: ink, opacity: .62, fontSize: "2.7cqw", letterSpacing: ".12em", marginTop: "8cqh" }} />}
    </div>
  );
}
function ArtStats({ d, ink, edit, update }) {
  const t = PS_DATA.TEMPLATES.find(x => x.id === "birth");
  const stats = (t && t.stats) || [];
  return (
    <div style={{ height: "100%", display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", textAlign: "center", padding: "11cqw 8cqw" }}>
      <div style={{ fontFamily: 'var(--poster-sans)', color: ink, opacity: .6, fontSize: "2.9cqw", letterSpacing: ".4em", fontWeight: 700, marginBottom: "3cqh" }}>HELLO WORLD</div>
      <Txt edit={edit} update={update} value={d.headline} field="headline" multiline style={{ fontFamily: fontCss(d.font), color: ink, fontSize: "13cqw", lineHeight: .98, fontWeight: 700, whiteSpace: "pre-line" }} />
      <Txt edit={edit} update={update} value={d.subline} field="subline" style={{ fontFamily: 'var(--poster-sans)', color: ink, opacity: .78, fontSize: "3.2cqw", letterSpacing: ".18em", margin: "5cqh 0 8cqh", fontWeight: 600 }} />
      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: "0", width: "78cqw", borderTop: `1px solid ${ink}`, borderLeft: `1px solid ${ink}`, borderColor: ink, opacity: 1 }}>
        {stats.map((s, i) => (
          <div key={i} style={{ borderRight: `1px solid ${ink}`, borderBottom: `1px solid ${ink}`, padding: "4cqw 2cqw", borderColor: ink }}>
            <div style={{ fontFamily: 'var(--poster-sans)', color: ink, opacity: .55, fontSize: "2.3cqw", letterSpacing: ".2em", fontWeight: 700 }}>{s[0].toUpperCase()}</div>
            <div style={{ fontFamily: fontCss(d.font), color: ink, fontSize: "4.6cqw", marginTop: "1.5cqw", fontWeight: 600 }}>{s[1]}</div>
          </div>
        ))}
      </div>
    </div>
  );
}

/* photo crop guides — trim edge + dashed safe area + corner brackets (editor only) */
function CropGuides() {
  const br = { position: "absolute", width: "5cqw", height: "5cqw", borderColor: "rgba(255,255,255,.92)", borderStyle: "solid", filter: "drop-shadow(0 0 1px rgba(0,0,0,.6))" };
  return (
    <div style={{ position: "absolute", inset: 0, pointerEvents: "none", zIndex: 2 }}>
      <div style={{ position: "absolute", inset: "6cqw", border: "1px dashed rgba(255,255,255,.7)", boxShadow: "0 0 0 1px rgba(0,0,0,.25)" }} />
      <div style={{ ...br, top: "6cqw", left: "6cqw", borderWidth: "1.5px 0 0 1.5px" }} />
      <div style={{ ...br, top: "6cqw", right: "6cqw", borderWidth: "1.5px 1.5px 0 0" }} />
      <div style={{ ...br, bottom: "6cqw", left: "6cqw", borderWidth: "0 0 1.5px 1.5px" }} />
      <div style={{ ...br, bottom: "6cqw", right: "6cqw", borderWidth: "0 1.5px 1.5px 0" }} />
      <div style={{ position: "absolute", top: "1.4cqw", left: "50%", transform: "translateX(-50%)", padding: ".7cqh 2.4cqw", borderRadius: "99px", background: "rgba(28,22,16,.55)", color: "#FBF4E8", fontFamily: "var(--poster-sans)", fontSize: "2.1cqw", fontWeight: 700, letterSpacing: ".12em", backdropFilter: "blur(2px)" }}>SAFE AREA</div>
    </div>
  );
}

function ArtPhoto({ d, ink, live, update, edit }) {
  const drag = (typeof usePhotoDrag === "function") ? usePhotoDrag(d, live ? update : null) : {};
  const pt = d.photoT || { zoom: 1, ox: 0, oy: 0 };
  const interactive = live && d.photo;
  return (
    <div style={{ height: "100%", display: "flex", flexDirection: "column" }}>
      <div
        style={{ flex: 1, position: "relative", overflow: "hidden", background: d.photo ? "transparent" : "rgba(255,255,255,.05)", cursor: interactive ? "grab" : "default", touchAction: interactive ? "none" : "auto" }}
        {...(interactive ? drag : {})}
      >
        {d.photo ? (
          <img src={d.photo} alt="" draggable={false} style={{ position: "absolute", inset: 0, width: "100%", height: "100%", objectFit: "cover", display: "block", transform: `translate(${pt.ox}%, ${pt.oy}%) scale(${pt.zoom})`, transformOrigin: "center", userSelect: "none", pointerEvents: "none" }} />
        ) : (
          <div style={{ position: "absolute", inset: 0, display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", color: ink, opacity: .5, gap: "3cqh" }}>
            <Icon name="ImagePlus" size={0} style={{ width: "11cqw", height: "11cqw" }} stroke={1.5} />
            <div style={{ fontFamily: 'var(--poster-sans)', fontSize: "3cqw", letterSpacing: ".18em", fontWeight: 600 }}>YOUR PHOTO</div>
          </div>
        )}
        {interactive && <CropGuides />}
        {interactive && (
          <div style={{ position: "absolute", left: "50%", bottom: "2.4cqh", transform: "translateX(-50%)", display: "flex", alignItems: "center", gap: "1.4cqw", padding: "1.4cqh 3cqw", borderRadius: "99px", background: "rgba(28,22,16,.6)", color: "#FBF4E8", fontFamily: "var(--poster-sans)", fontSize: "2.5cqw", fontWeight: 600, letterSpacing: ".04em", pointerEvents: "none", backdropFilter: "blur(2px)", zIndex: 3 }}>
            <Icon name="Move" size={0} style={{ width: "3cqw", height: "3cqw" }} /> Drag to reposition
          </div>
        )}
      </div>
      <div style={{ padding: "6cqw 7cqw 7cqw", textAlign: "left" }}>
        <Txt edit={edit} update={update} value={d.headline} field="headline" style={{ fontFamily: fontCss(d.font), color: ink, fontSize: "6.6cqw", lineHeight: 1.05, fontWeight: 600 }} />
        <Txt edit={edit} update={update} value={d.subline} field="subline" style={{ fontFamily: 'var(--poster-sans)', color: ink, opacity: .7, fontSize: "2.9cqw", letterSpacing: ".3em", marginTop: "2.5cqw", fontWeight: 600 }} />
      </div>
    </div>
  );
}
function ArtCoords({ d, ink, edit, update }) {
  return (
    <div style={{ height: "100%", display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", textAlign: "center", padding: "12cqw 6cqw" }}>
      <div style={{ width: "5cqw", height: "5cqw", borderRadius: "50%", border: `1.5px solid ${ink}`, position: "relative", marginBottom: "8cqh" }}>
        <div style={{ position: "absolute", inset: "32%", borderRadius: "50%", background: ink }} />
      </div>
      <Txt edit={edit} update={update} value={d.headline} field="headline" multiline style={{ fontFamily: fontCss(d.font), color: ink, fontSize: "13cqw", lineHeight: 1, fontWeight: 600, letterSpacing: ".04em", whiteSpace: "pre-line" }} />
      <Txt edit={edit} update={update} value={d.subline} field="subline" style={{ fontFamily: 'var(--poster-sans)', color: ink, opacity: .78, fontSize: "3.6cqw", letterSpacing: ".5em", margin: "4cqh 0 6cqh", fontWeight: 600 }} />
      <div style={{ width: "40cqw", height: "1px", background: ink, opacity: .5 }} />
      {(d.meta || edit) && <Txt edit={edit} update={update} value={d.meta} field="meta" style={{ fontFamily: fontCss(d.font), color: ink, opacity: .8, fontSize: "3.6cqw", letterSpacing: ".06em", marginTop: "6cqh" }} />}
    </div>
  );
}
function ArtAnniversary({ d, ink, edit, update }) {
  const lines = (d.headline || "").split("\n");
  return (
    <div style={{ height: "100%", display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", textAlign: "center", padding: "12cqw 8cqw" }}>
      {edit && update ? (
        <EditableText value={d.headline} field="headline" update={update} multiline style={{ fontFamily: fontCss(d.font), color: ink, fontSize: "14cqw", lineHeight: 1.08, fontWeight: 500, whiteSpace: "pre-line" }} />
      ) : (
        <div style={{ fontFamily: fontCss(d.font), color: ink, fontSize: "14cqw", lineHeight: 1.08, fontWeight: 500 }}>
          {lines.map((l, i) => (
            <div key={i} style={ l.trim() === "&" ? { fontSize: "16cqw", fontStyle: "italic", opacity: .85, margin: "1cqh 0" } : null }>{l}</div>
          ))}
        </div>
      )}
      <Txt edit={edit} update={update} value={d.subline} field="subline" style={{ fontFamily: 'var(--poster-sans)', color: ink, opacity: .75, fontSize: "3cqw", letterSpacing: ".34em", marginTop: "8cqh", fontWeight: 600 }} />
    </div>
  );
}

/* ---- Custom template renderer: background + fixed-style text zones + photo zone(s) ---- */
function ArtCustom({ d, ink, live, update, edit }) {
  const zones = d.zones || [];
  const bg = d.bgCustom || { type: "color", value: "#ECE2D0" };
  const baseInk = d.ink || ink || "#3A2D20";
  const photos = d.photos || {};
  const pdrag = useRefPv(null);
  const setZoneText = (id, text) => {
    if (!update) return;
    update({ zones: zones.map(z => z.id === id ? { ...z, text } : z) });
  };
  // independent drag-to-reposition per photo zone (customer/live only)
  const photoHandlers = (zid) => {
    if (!(live && update)) return {};
    return {
      onPointerDown: e => {
        const p = photos[zid]; if (!p) return;
        try { e.currentTarget.setPointerCapture(e.pointerId); } catch (_) {}
        pdrag.current = { zid, x: e.clientX, y: e.clientY, rect: e.currentTarget.getBoundingClientRect(), ox: p.ox || 0, oy: p.oy || 0, zoom: p.zoom || 1 };
      },
      onPointerMove: e => {
        const dg = pdrag.current; if (!dg || dg.zid !== zid) return;
        const lim = Math.max(0, (dg.zoom - 1) * 50);
        const nx = Math.max(-lim, Math.min(lim, dg.ox + (e.clientX - dg.x) / dg.rect.width * 100));
        const ny = Math.max(-lim, Math.min(lim, dg.oy + (e.clientY - dg.y) / dg.rect.height * 100));
        update({ photos: { ...photos, [zid]: { ...photos[zid], ox: nx, oy: ny } } });
      },
      onPointerUp: e => { pdrag.current = null; try { e.currentTarget.releasePointerCapture(e.pointerId); } catch (_) {} },
      onPointerCancel: () => { pdrag.current = null; },
    };
  };
  return (
    <div style={{ position: "absolute", inset: 0, overflow: "hidden" }}>
      {bg.type === "image" && bg.value
        ? <img src={bg.value} alt="" draggable={false} style={{ position: "absolute", inset: 0, width: "100%", height: "100%", objectFit: "cover" }} />
        : <div style={{ position: "absolute", inset: 0, background: bg.value || "#ECE2D0" }} />}
      {zones.map(z => {
        if (z.type === "photo") {
          const ph = photos[z.id];
          const interactive = live && update && !!ph;
          return (
            <div key={z.id}
              style={{ position: "absolute", left: z.x + "%", top: z.y + "%", width: z.w + "%", height: (z.h || 40) + "%", transform: "translate(-50%, -50%)", borderRadius: z.shape === "circle" ? "50%" : (z.radius || 0) + "cqw", overflow: "hidden", background: ph ? "transparent" : "rgba(0,0,0,.06)", cursor: interactive ? "grab" : "default", touchAction: interactive ? "none" : "auto", boxShadow: ph ? "none" : "inset 0 0 0 1.5px rgba(58,45,32,.22)" }}
              {...(interactive ? photoHandlers(z.id) : {})}>
              {ph
                ? <img src={ph.src} alt="" draggable={false} style={{ position: "absolute", inset: 0, width: "100%", height: "100%", objectFit: "cover", transform: `translate(${ph.ox || 0}%, ${ph.oy || 0}%) scale(${ph.zoom || 1})`, pointerEvents: "none" }} />
                : <div style={{ position: "absolute", inset: 0, display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", gap: "2cqh", color: baseInk, opacity: .5 }}>
                    <Icon name="ImagePlus" size={0} style={{ width: "8cqw", height: "8cqw" }} stroke={1.5} />
                    <span style={{ fontFamily: "var(--poster-sans)", fontSize: "2.4cqw", fontWeight: 600, letterSpacing: ".16em" }}>YOUR PHOTO</span>
                  </div>}
            </div>
          );
        }
        const col = z.color || baseInk;
        const common = {
          position: "absolute", left: z.x + "%", top: z.y + "%", width: z.w + "%",
          transform: "translate(-50%, -50%)", textAlign: z.align,
          fontFamily: fontCss(z.font), fontWeight: z.weight, color: col, opacity: z.opacity,
          fontSize: z.size + "cqw", lineHeight: z.lineHeight,
          letterSpacing: (z.tracking || 0) + "em", textTransform: z.uppercase ? "uppercase" : "none",
          whiteSpace: "pre-line", wordBreak: "break-word",
        };
        if (edit && update) {
          return <EditableText key={z.id} value={z.text} field="__zone" multiline
            update={v => setZoneText(z.id, v.__zone !== undefined ? v.__zone : v)} style={common} />;
        }
        return <div key={z.id} style={common}>{z.text}</div>;
      })}
    </div>
  );
}

const ART = { quote: ArtQuote, name: ArtName, stats: ArtStats, photo: ArtPhoto, coords: ArtCoords, anniversary: ArtAnniversary, custom: ArtCustom };

function PosterArt({ d, live, update, edit }) {
  const ink = d.textColor;
  if (d.custom || (d.zones && d.zones.length)) {
    return (
      <div className="poster-art" style={{ width: "100%", height: "100%", containerType: "size", position: "relative", background: (d.bgCustom && d.bgCustom.type === "color") ? d.bgCustom.value : "#ECE2D0" }}>
        <ArtCustom d={d} ink={d.ink || ink} live={live} update={update} edit={edit} />
      </div>
    );
  }
  const t = PS_DATA.TEMPLATES.find(x => x.id === d.templateId) || PS_DATA.TEMPLATES[0];
  const Comp = ART[t.kind] || ArtQuote;
  return (
    <div className="poster-art" style={{ width: "100%", height: "100%", background: bgHex(d.bg), containerType: "size", position: "relative" }}>
      <Comp d={d} ink={ink} live={live} update={update} edit={edit} />
    </div>
  );
}

/* ---- Framed poster ---- */
function Poster({ d, maxW, maxH, shadow = true, animateKey, live, update, edit }) {
  const size = PS_DATA.SIZES.find(s => s.id === d.size) || PS_DATA.SIZES[1];
  const frame = PS_DATA.FRAMES.find(f => f.id === d.frame) || PS_DATA.FRAMES[0];
  const ratio = size.ratio; // w/h
  const framed = frame.id !== "none";

  // sizing: fit within maxW/maxH while keeping ratio
  let w = maxW, h = w / ratio;
  if (maxH && h > maxH) { h = maxH; w = h * ratio; }

  const framePad = framed ? Math.max(8, w * 0.035) : 0;
  const matPad = framed ? Math.max(6, w * 0.028) : 0;

  return (
    <div
      key={animateKey}
      style={{
        width: w, height: h, position: "relative",
        background: framed ? frame.cssVar : "transparent",
        padding: framePad,
        borderRadius: framed ? 3 : 1,
        boxShadow: shadow ? "var(--sh-poster)" : "none",
        transition: "width .35s var(--ease), height .35s var(--ease)",
      }}
    >
      {framed && (
        <div style={{ position: "absolute", inset: framePad, boxShadow: "inset 0 2px 5px rgba(0,0,0,.35), inset 0 -1px 2px rgba(255,255,255,.15)", pointerEvents: "none", zIndex: 3 }} />
      )}
      <div style={{
        width: "100%", height: "100%", overflow: "hidden",
        background: frame.id === "white" || frame.id === "oak" ? "#FCF9F1" : "transparent",
        padding: matPad,
        boxShadow: framed ? "0 0 0 1px rgba(0,0,0,.06)" : "none",
      }}>
        <div style={{ width: "100%", height: "100%", overflow: "hidden", boxShadow: framed ? "0 1px 4px rgba(0,0,0,.18)" : "none" }}>
          <PosterArt d={d} live={live} update={update} edit={edit} />
        </div>
      </div>
    </div>
  );
}

/* ---- Room scene: poster centered on a warm wall ---- */
function RoomScene({ d, maxH = 460, live, update, edit, children }) {
  return (
    <div style={{
      position: "relative", width: "100%", height: "100%",
      display: "flex", alignItems: "center", justifyContent: "center",
      background: "radial-gradient(120% 90% at 50% 12%, #EFE6D5 0%, #E3D7C0 55%, #D6C8AC 100%)",
      overflow: "hidden",
    }}>
      {/* floor line */}
      <div style={{ position: "absolute", left: 0, right: 0, bottom: 0, height: "22%", background: "linear-gradient(#CBB893,#BCA67E)", boxShadow: "inset 0 2px 6px rgba(0,0,0,.12)" }} />
      {/* soft light */}
      <div style={{ position: "absolute", inset: 0, background: "radial-gradient(60% 50% at 50% 30%, rgba(255,250,238,.55), rgba(255,250,238,0) 70%)" }} />
      <div style={{ position: "relative", zIndex: 2, paddingBottom: "6%" }}>
        <Poster d={d} maxH={maxH} maxW={maxH * (d ? (PS_DATA.SIZES.find(s=>s.id===d.size)||{ratio:.75}).ratio : .75)} live={live} update={update} edit={edit} />
      </div>
      {children}
    </div>
  );
}

Object.assign(window, { Poster, PosterArt, RoomScene, EditableText, bgHex, fontCss });
