/* Sosh Insider — Bali :: chapter window (masonry) + lightbox */

/* ---------- thumbnail in the contact sheet ---------- */
function Thumb({ frame, tint, onOpen, big }) {
  const [hover, setHover] = useState(false);
  return (
    <div
      data-clickable
      onClick={() => {
        window.SFX && SFX.shutter();
        onOpen();
      }}
      onMouseEnter={() => setHover(true)}
      onMouseLeave={() => setHover(false)}
      style={{
        breakInside: "avoid",
        marginBottom: 10,
        border: "2px solid var(--line)",
        background: "var(--paper)",
        boxShadow: hover ? "4px 5px 0 rgba(43,38,34,0.32)" : "2px 2px 0 rgba(43,38,34,0.2)",
        transform: hover ? "translate(-1px,-2px)" : "none",
        transition: "transform 0.1s, box-shadow 0.1s",
        position: "relative",
      }}
    >
      <PhotoPlaceholder frame={frame} tint={tint} big={big} showCaption={big} />
      <div
        className="mono"
        style={{
          position: "absolute",
          bottom: 0,
          right: 0,
          background: "var(--ink)",
          color: "#fff",
          fontSize: 11,
          padding: "0 5px",
          opacity: hover ? 1 : 0.0,
          transition: "opacity 0.1s",
        }}
      >
        OPEN ⤢
      </div>
    </div>
  );
}

/* ---------- chapter window ---------- */
function ChapterWindow({ chapter, geom, onTitleDown, onClose, onBack, onOpenFrame, onDownloadAll }) {
  const featured = chapter.frames.filter((f) => f.featured);
  const rest = chapter.frames.filter((f) => !f.featured);
  const empty = chapter.frames.length === 0;

  return (
    <MacWindow
      title={chapter.title + "  —  " + chapter.roll}
      onClose={onClose}
      onTitleDown={onTitleDown}
      style={{ left: geom.x, top: geom.y, width: geom.w, height: geom.h, zIndex: 1000 }}
    >
      {/* toolbar */}
      <div
        style={{
          display: "flex",
          alignItems: "center",
          gap: 8,
          padding: "7px 9px",
          borderBottom: "2px solid var(--line)",
          background: "var(--paper2)",
          flexWrap: "wrap",
        }}
      >
        <PixelButton onClick={onBack}>‹ Chapters</PixelButton>
        <div className="mono" style={{ fontSize: 14, color: "var(--ink-soft)", whiteSpace: "nowrap" }}>
          {chapter.place} · {chapter.date}
        </div>
        <div style={{ flex: 1 }} />
        <span className="mono" style={{ fontSize: 14, whiteSpace: "nowrap", flex: "0 0 auto" }}>
          {chapter.count} frames
        </span>
        {!empty && (
          <PixelButton accent onClick={onDownloadAll} title="Download all frames in this roll">
            ⤓ Download All
          </PixelButton>
        )}
      </div>

      {/* body */}
      <div className="scroller" style={{ background: "var(--paper)" }}>
        {/* intro */}
        <div style={{ padding: "20px 22px 6px", maxWidth: 720 }}>
          <div className="serif" style={{ fontSize: "clamp(28px,3.4vw,42px)", lineHeight: 1.02, letterSpacing: "-0.01em" }}>
            {chapter.title}
          </div>
          <div className="serif" style={{ fontSize: 17, fontStyle: "italic", lineHeight: 1.5, color: "var(--ink-soft)", marginTop: 10 }}>
            {chapter.blurb}
          </div>
        </div>

        {empty && (
          <div style={{ padding: "30px 22px 40px" }}>
            <div style={{ border: "2px dashed rgba(43,38,34,0.4)", padding: "28px 20px", textAlign: "center", background: "var(--paper2)" }}>
              <div className="pixel" style={{ fontSize: 11, textTransform: "uppercase", letterSpacing: 1 }}>Still in the darkroom</div>
              <div className="serif" style={{ fontSize: 16, fontStyle: "italic", color: "var(--ink-soft)", marginTop: 8, lineHeight: 1.5 }}>
                This roll's frames haven't been loaded yet.<br />Run the manifest generator and redeploy to develop them.
              </div>
            </div>
          </div>
        )}

        {/* featured */}
        {!empty && (
        <div style={{ padding: "14px 18px 4px" }}>
          <SectionLabel>Featured frames</SectionLabel>
          <div
            style={{
              display: "grid",
              gridTemplateColumns: "repeat(auto-fill, minmax(220px, 1fr))",
              gap: 12,
              marginTop: 10,
            }}
          >
            {featured.map((f) => (
              <Thumb
                key={f.id}
                frame={f}
                tint={chapter.tint}
                big
                onOpen={() => onOpenFrame(chapter.frames.indexOf(f))}
              />
            ))}
          </div>
        </div>
        )}

        {/* contact sheet (masonry) */}
        {!empty && rest.length > 0 && (
        <div style={{ padding: "16px 18px 26px" }}>
          <SectionLabel>Contact sheet — {rest.length} more</SectionLabel>
          <div
            style={{
              columnWidth: 168,
              columnGap: 10,
              marginTop: 12,
            }}
          >
            {rest.map((f) => (
              <Thumb
                key={f.id}
                frame={f}
                tint={chapter.tint}
                onOpen={() => onOpenFrame(chapter.frames.indexOf(f))}
              />
            ))}
          </div>
        </div>
        )}
      </div>
    </MacWindow>
  );
}

function SectionLabel({ children }) {
  return (
    <div
      style={{
        display: "flex",
        alignItems: "center",
        gap: 9,
        color: "var(--ink-soft)",
      }}
    >
      <span className="pixel" style={{ fontSize: 8.5, textTransform: "uppercase", letterSpacing: 0.5, whiteSpace: "nowrap" }}>
        {children}
      </span>
      <span style={{ flex: 1, height: 2, background: "repeating-linear-gradient(to right, var(--ink) 0 3px, transparent 3px 6px)", opacity: 0.4 }} />
    </div>
  );
}

/* ---------- save button (lightbox) ---------- */
function SaveButton({ frame, onDownload }) {
  const [state, setState] = React.useState("idle");
  const click = async () => {
    if (state === "saving") return;
    setState("saving");
    try {
      const ok = await onDownload(frame);
      setState(ok === false ? "error" : "done");
    } catch (e) {
      setState("error");
    }
    setTimeout(() => setState("idle"), 1800);
  };
  const label = state === "saving" ? "⤓ Saving…"
    : state === "done" ? "✓ Saved"
    : state === "error" ? "× Failed"
    : "⤓ Save";
  return <PixelButton accent onClick={click}>{label}</PixelButton>;
}

/* ---------- lightbox ---------- */
function Lightbox({ chapter, index, onClose, onNav, onDownload }) {
  const frame = chapter.frames[index];

  useEffect(() => {
    const onKey = (e) => {
      if (e.key === "Escape") onClose();
      else if (e.key === "ArrowRight") onNav(1);
      else if (e.key === "ArrowLeft") onNav(-1);
    };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [index]);

  return (
    <div
      style={{
        position: "fixed",
        inset: 0,
        zIndex: 4000,
        background: "rgba(20,16,13,0.86)",
        display: "flex",
        alignItems: "center",
        justifyContent: "center",
        padding: "40px 16px",
      }}
      onMouseDown={(e) => {
        if (e.target === e.currentTarget) onClose();
      }}
    >
      {/* prev / next big arrows */}
      <NavArrow dir={-1} onClick={() => onNav(-1)} />
      <MacWindow
        title={chapter.roll + " · " + frame.file}
        onClose={onClose}
        zoomable={false}
        style={{
          position: "relative",
          maxWidth: "min(92vw, 1000px)",
          maxHeight: "86vh",
        }}
      >
        <div
          style={{
            background: "#1c1814",
            padding: "18px 18px 14px",
            display: "flex",
            flexDirection: "column",
            alignItems: "center",
          }}
        >
          {frame.url ? (
            <img
              src={frame.url}
              alt={frame.caption || frame.file}
              decoding="async"
              style={{
                display: "block",
                maxWidth: "min(86vw, 900px)",
                maxHeight: "66vh",
                width: "auto",
                height: "auto",
                border: "1px solid rgba(255,255,255,0.12)",
              }}
            />
          ) : (
            <div style={{ width: "min(82vw, " + Math.round(62 * frame.aspect) + "vh, 900px)", maxWidth: "100%" }}>
              <PhotoPlaceholder frame={frame} tint={chapter.tint} big />
            </div>
          )}
          <div
            className="serif"
            style={{ color: "#e7d8bf", fontSize: 15, fontStyle: "italic", marginTop: 12, textAlign: "center" }}
          >
            {frame.caption}
          </div>
        </div>
        {/* footer toolbar */}
        <div
          style={{
            display: "flex",
            alignItems: "center",
            gap: 10,
            padding: "8px 10px",
            borderTop: "2px solid var(--line)",
            background: "var(--paper2)",
          }}
        >
          <PixelButton onClick={() => onNav(-1)}>‹ Prev</PixelButton>
          <div style={{ flex: 1, textAlign: "center" }}>
            <span className="mono" style={{ fontSize: 15 }}>
              {chapter.title} · {frame.no} / {chapter.count}
            </span>
          </div>
          <SaveButton frame={frame} onDownload={onDownload} />
          <PixelButton onClick={() => onNav(1)}>Next ›</PixelButton>
        </div>
      </MacWindow>
      <NavArrow dir={1} onClick={() => onNav(1)} />
    </div>
  );
}

function NavArrow({ dir, onClick }) {
  return (
    <button
      onClick={() => {
        window.SFX && SFX.shutter();
        onClick();
      }}
      className="pixel nav-arrow"
      style={{
        flex: "0 0 auto",
        width: 44,
        height: 64,
        margin: "0 6px",
        background: "var(--paper)",
        border: "2px solid var(--line)",
        boxShadow: "3px 3px 0 rgba(0,0,0,0.4)",
        fontSize: 18,
        color: "var(--ink)",
        display: "flex",
        alignItems: "center",
        justifyContent: "center",
      }}
      aria-label={dir < 0 ? "Previous" : "Next"}
    >
      {dir < 0 ? "‹" : "›"}
    </button>
  );
}

Object.assign(window, { ChapterWindow, Lightbox, Thumb, SectionLabel });

/* ---------- video clip card ---------- */
function VideoClipCard({ clip, index, onPlay }) {
  const [hover, setHover] = useState(false);
  return (
    <div
      data-clickable
      onClick={() => { window.SFX && SFX.shutter(); onPlay(index); }}
      onMouseEnter={() => setHover(true)}
      onMouseLeave={() => setHover(false)}
      style={{
        background: "#2b2622",
        border: "2px solid var(--line)",
        boxShadow: hover ? "4px 5px 0 rgba(43,38,34,0.32)" : "2px 2px 0 rgba(43,38,34,0.2)",
        transform: hover ? "translate(-1px,-2px)" : "none",
        transition: "transform 0.1s, box-shadow 0.1s",
        overflow: "hidden",
      }}
    >
      <div style={{ position: "relative", aspectRatio: "16 / 9", borderBottom: "2px solid var(--line)" }}>
        <VideoScreen clip={clip} playing={hover} tint={clip.tint} />
        <div style={{ position: "absolute", inset: 0, display: "flex", alignItems: "center", justifyContent: "center" }}>
          <div style={{ width: 38, height: 38, border: "2px solid rgba(255,255,255,0.9)", background: "rgba(20,16,13,0.3)", color: "#fff", display: "flex", alignItems: "center", justifyContent: "center", fontSize: 14 }}>▶</div>
        </div>
        <div className="mono" style={{ position: "absolute", bottom: 6, right: 7, background: "rgba(11,11,11,0.7)", color: "#e8feff", fontSize: 11, padding: "0 4px" }}>{clip.runtime}</div>
      </div>
      <div style={{ padding: "8px 10px", background: "var(--paper)" }}>
        <div className="pixel" style={{ fontSize: 9, textTransform: "uppercase" }}>{clip.title}</div>
        <div className="mono" style={{ fontSize: 12.5, color: "var(--ink-soft)", marginTop: 2 }}>{clip.place}</div>
      </div>
    </div>
  );
}

/* ---------- video album window ---------- */
function VideoChapterWindow({ chapter, geom, onTitleDown, onClose, onBack, onPlayClip, onDrive }) {
  return (
    <MacWindow
      title={chapter.title + "  —  " + chapter.roll}
      onClose={onClose}
      onTitleDown={onTitleDown}
      style={{ left: geom.x, top: geom.y, width: geom.w, height: geom.h, zIndex: 1000 }}
    >
      <div style={{ display: "flex", alignItems: "center", gap: 8, padding: "7px 9px", borderBottom: "2px solid var(--line)", background: "var(--paper2)", flexWrap: "wrap" }}>
        <PixelButton onClick={onBack}>‹ Albums</PixelButton>
        <div className="mono" style={{ fontSize: 14, color: "var(--ink-soft)", whiteSpace: "nowrap" }}>{chapter.place} · {chapter.date}</div>
        <div style={{ flex: 1 }} />
        <span className="mono" style={{ fontSize: 14, whiteSpace: "nowrap", flex: "0 0 auto" }}>{chapter.count} clips</span>
        <PixelButton accent onClick={onDrive} title="Open the full reel on Google Drive">⤓ Watch all on Drive</PixelButton>
      </div>

      <div className="scroller" style={{ background: "var(--paper)" }}>
        <div style={{ padding: "20px 22px 6px", maxWidth: 720 }}>
          <div className="serif" style={{ fontSize: "clamp(28px,3.4vw,42px)", lineHeight: 1.02, letterSpacing: "-0.01em" }}>{chapter.title}</div>
          <div className="serif" style={{ fontSize: 17, fontStyle: "italic", lineHeight: 1.5, color: "var(--ink-soft)", marginTop: 10 }}>{chapter.blurb}</div>
        </div>

        <div style={{ padding: "14px 18px 4px" }}>
          <SectionLabel>Reels living here — {chapter.count}</SectionLabel>
          <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(240px, 1fr))", gap: 12, marginTop: 12 }}>
            {chapter.videos.map((clip, i) => (
              <VideoClipCard key={clip.id} clip={clip} index={i} onPlay={onPlayClip} />
            ))}
          </div>
        </div>

        {/* Drive panel */}
        <div style={{ padding: "18px 18px 26px" }}>
          <div
            style={{
              border: "2px solid var(--line)",
              background: "linear-gradient(180deg, var(--paper2), var(--paper))",
              padding: "18px 18px",
              display: "flex",
              gap: 16,
              alignItems: "center",
              flexWrap: "wrap",
            }}
          >
            <div style={{ flex: "1 1 280px", minWidth: 0 }}>
              <div className="pixel" style={{ fontSize: 10, textTransform: "uppercase" }}>The rest of the footage</div>
              <div className="serif" style={{ fontSize: 16.5, lineHeight: 1.5, color: "var(--ink-soft)", marginTop: 6 }}>
                The full dive is far too heavy to keep on this disk — another <strong style={{ color: "var(--ink)" }}>{chapter.driveCount}+ reels</strong> are mirrored to Google Drive. Same trip, every roll the camera ran underwater.
              </div>
            </div>
            <PixelButton accent onClick={onDrive} style={{ fontSize: 10, padding: "10px 16px" }}>↗ Open Drive folder</PixelButton>
          </div>
        </div>
      </div>
    </MacWindow>
  );
}

Object.assign(window, { VideoClipCard, VideoChapterWindow });
