// portfolio.jsx — Gallery, filter chips, lightbox.
// Exposed globally for the main app script to consume.

const WORKS = [
{ id: "work-1",  title: "A Colourful Life",         year: 2025, kind: "Personal Work", publisher: "Instagram Challenge",      aspect: "portrait" },
{ id: "work-2",  title: "Lost",                     year: 2025, kind: "Picture Book",  publisher: "New Life Stories",         aspect: "landscape" },
{ id: "work-3",  title: "Run!",                     year: 2025, kind: "Picture Book",  publisher: "New Life Stories",         aspect: "portrait" },
{ id: "work-4",  title: "Life Faraway",             year: 2025, kind: "Picture Book",  publisher: "Grandpa's Little Star",    aspect: "square" },
{ id: "work-5",  title: "Little Star's New Friends",year: 2025, kind: "Picture Book",  publisher: "Grandpa's Little Star",    aspect: "landscape" },
{ id: "work-6",  title: "My Sister",                year: 2025, kind: "Personal Work", publisher: "",                         aspect: "portrait" },
{ id: "work-7",  title: "Grit",                     year: 2025, kind: "Picture Book",  publisher: "New Life Stories",         aspect: "square" },
{ id: "work-8",  title: "Grit",                     year: 2025, kind: "Picture Book",  publisher: "New Life Stories",         aspect: "landscape" },
{ id: "work-9",  title: "It's Okay",                year: 2025, kind: "Picture Book",  publisher: "New Life Stories",         aspect: "square" },
{ id: "work-10", title: "A Sparkle in Your Eyes",   year: 2025, kind: "Picture Book",  publisher: "Grandpa's Little Star",    aspect: "square" },
{ id: "work-11", title: "Ocean",                    year: 2025, kind: "Toy",           publisher: "Playfully Puzzle",         aspect: "landscape" },
{ id: "work-12", title: "First Day of School",      year: 2025, kind: "Picture Book",  publisher: "Etonhouse Community Fund", aspect: "portrait" }];


const FILTERS = ["All work", "Picture Books", "Personal Work", "Toys"];

function matchFilter(work, filter) {
  if (filter === "All work") return true;
  if (filter === "Picture Books") return work.kind === "Picture Book" || work.kind === "Cover";
  if (filter === "Personal Work") return work.kind === "Personal Work";
  if (filter === "Toys") return work.kind === "Toy";
  return true;
}

// Tape strips for the scrapbook look — subtle, sparingly applied.
function TapeStrip({ side = "tl", rotate = -8 }) {
  const positions = {
    tl: { top: -10, left: 18 },
    tr: { top: -10, right: 18 },
    bl: { bottom: -10, left: 18 },
    br: { bottom: -10, right: 18 }
  };
  return (
    <span
      aria-hidden="true"
      style={{
        position: "absolute",
        ...positions[side],
        width: 64,
        height: 18,
        background: "rgba(244, 232, 200, 0.78)",
        boxShadow: "0 2px 6px rgba(60,40,20,.08)",
        transform: `rotate(${rotate}deg)`,
        borderLeft: "1px dashed rgba(60,40,20,.08)",
        borderRight: "1px dashed rgba(60,40,20,.08)"
      }} />);


}

function WorkCard({ work, layout, onOpen, palette, tape }) {
  // Aspect ratio per layout.
  let ratio;
  if (layout === "uniform") ratio = "4 / 5";else
  if (layout === "masonry") {
    ratio = work.aspect === "portrait" ? "3 / 4" : work.aspect === "landscape" ? "4 / 3" : "1 / 1";
  } else {
    // editorial — handled by the parent grid via spans
    ratio = work.aspect === "portrait" ? "3 / 4" : work.aspect === "landscape" ? "16 / 10" : "1 / 1";
  }

  return (
    <figure
      className="vg-card"
      onClick={() => onOpen(work)}
      style={{ margin: 0, position: "relative", cursor: "pointer" }}>
      
      <div
        className="vg-card-frame"
        style={{
          aspectRatio: ratio,
          background: palette.frame,
          padding: 10,
          boxShadow: "0 1px 0 rgba(255,255,255,.6) inset, 0 18px 30px -22px rgba(60,40,20,.45)",
          position: "relative",
          transition: "transform .35s ease, box-shadow .35s ease"
        }}>
        
        {tape && <TapeStrip side="tl" rotate={-7} />}
        <image-slot
          id={work.id}
          shape="rect"
          placeholder={`${work.title} — drop image`}
          style={{ width: "100%", height: "100%", display: "block" }}>
        </image-slot>
      </div>
      <figcaption style={{ marginTop: 14, display: "flex", justifyContent: "space-between", alignItems: "baseline", gap: "12px" }}>
        <div>
          <div style={{ lineHeight: 1.15, color: palette.ink, fontFamily: "serif", letterSpacing: "1.7px", fontSize: "16px" }}>
            {work.title}
          </div>
          <div style={{ fontSize: 12, color: palette.muted, marginTop: 4, letterSpacing: ".01em" }}>
            {work.kind}{work.publisher ? ` · ${work.publisher}` : ""}
          </div>
        </div>
        <div style={{ fontSize: 12, color: palette.muted, fontVariantNumeric: "tabular-nums", fontFamily: "var(--vg-body)" }}>
          {work.year}
        </div>
      </figcaption>
    </figure>);

}

function Gallery({ layout, filter, setFilter, palette, onOpen, tape }) {
  const filtered = WORKS.filter((w) => matchFilter(w, filter));

  let gridStyle, gridAttr;
  if (layout === "uniform") {
    gridStyle = { display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: "44px 36px" };
    gridAttr = "gallery-uniform";
  } else if (layout === "masonry") {
    gridStyle = { columnCount: 3, columnGap: 36 };
    gridAttr = "gallery-masonry";
  } else {
    // editorial — 6-col grid, hand-tuned spans for rhythm
    gridStyle = { display: "grid", gridTemplateColumns: "repeat(6, 1fr)", gap: "44px 36px" };
    gridAttr = "gallery-editorial";
  }

  return (
    <section id="work" data-vg-section="work" style={{ padding: "120px 80px 100px", background: palette.bg }}>
      <header style={{ display: "flex", alignItems: "flex-end", justifyContent: "space-between", marginBottom: 56, flexWrap: "wrap", gap: 24 }}>
        <div style={{ maxWidth: 640 }}>
          <div style={{ fontFamily: "var(--vg-body)", fontSize: 12, letterSpacing: ".22em", textTransform: "uppercase", color: palette.muted }}>
            Selected Work · 2021 — 2024
          </div>
          <h2 style={{ lineHeight: 1.02, margin: "16px 0 0", color: palette.ink, fontWeight: "500", fontSize: "45px", letterSpacing: "1.7px", fontFamily: "\"Playfair Display\"", width: "482px" }}>
            A little library of <em style={{ color: palette.primary, fontStyle: "italic", fontFamily: "serif", fontSize: "49px", letterSpacing: "-0.4px" }}>curious things</em>.
          </h2>
        </div>
        <div style={{ display: "flex", gap: 8, flexWrap: "wrap" }}>
          {FILTERS.map((f) => <button
            key={f}
            onClick={() => setFilter(f)}
            style={{
              appearance: "none",
              border: filter === f ? `1px solid ${palette.primary}` : `1px solid ${palette.line}`,
              background: filter === f ? palette.primary : "transparent",
              color: filter === f ? palette.bg : palette.ink,
              padding: "10px 16px",
              borderRadius: 999,
              fontFamily: "var(--vg-body)",
              fontSize: 13,
              letterSpacing: ".01em",
              cursor: "pointer",
              transition: "all .2s"
            }}>
            
              {f}
            </button>
          )}
        </div>
      </header>

      <div data-vg-grid={gridAttr} style={gridStyle}>
        {filtered.map((work, i) => {
          const tapeOn = tape && i % 4 === 0;
          if (layout === "masonry") {
            return (
              <div key={work.id} style={{ breakInside: "avoid", marginBottom: 44 }}>
                <WorkCard work={work} layout={layout} onOpen={onOpen} palette={palette} tape={tapeOn} />
              </div>);

          }
          if (layout === "editorial") {
            // Rhythm: large, small, small, medium-wide, small, small, repeating
            const pattern = [
            { col: "span 4", row: "span 1" },
            { col: "span 2", row: "span 1" },
            { col: "span 2", row: "span 1" },
            { col: "span 4", row: "span 1" },
            { col: "span 3", row: "span 1" },
            { col: "span 3", row: "span 1" }];

            const cell = pattern[i % pattern.length];
            return (
              <div key={work.id} style={{ gridColumn: cell.col, gridRow: cell.row }}>
                <WorkCard work={work} layout={layout} onOpen={onOpen} palette={palette} tape={tapeOn} />
              </div>);

          }
          return <WorkCard key={work.id} work={work} layout={layout} onOpen={onOpen} palette={palette} tape={tapeOn} />;
        })}
      </div>
    </section>);

}

function Lightbox({ work, onClose, palette }) {
  React.useEffect(() => {
    if (!work) return;
    const onKey = (e) => {if (e.key === "Escape") onClose();};
    window.addEventListener("keydown", onKey);
    document.body.style.overflow = "hidden";
    return () => {
      window.removeEventListener("keydown", onKey);
      document.body.style.overflow = "";
    };
  }, [work, onClose]);

  if (!work) return null;
  const ratio = work.aspect === "portrait" ? "3 / 4" : work.aspect === "landscape" ? "4 / 3" : "1 / 1";
  // Numeric ratio (width / height) for sizing the image container so it stays
  // proportional even when the viewport height constrains it.
  const numericRatio = work.aspect === "portrait" ? 0.75 : work.aspect === "landscape" ? 4 / 3 : 1;

  return (
    <div
      onClick={onClose}
      style={{
        position: "fixed", inset: 0, zIndex: 100,
        background: "rgba(30, 22, 14, 0.78)",
        backdropFilter: "blur(8px)",
        display: "grid", placeItems: "center",
        padding: 48,
        animation: "vgFade .25s ease-out"
      }}>
      
      {/* Floating close button — image-only lightbox, no sidebar text. */}
      <button
        onClick={(e) => {e.stopPropagation(); onClose();}}
        aria-label="Close"
        style={{
          position: "fixed",
          top: 20,
          right: 20,
          zIndex: 101,
          width: 44, height: 44,
          appearance: "none",
          border: "1px solid rgba(255,255,255,.35)",
          background: "rgba(0,0,0,.35)",
          color: palette.bg,
          borderRadius: "999px",
          fontSize: 24, lineHeight: 1,
          cursor: "pointer",
          backdropFilter: "blur(6px)",
          WebkitBackdropFilter: "blur(6px)"
        }}>
        ×
      </button>

      <div
        onClick={(e) => e.stopPropagation()}
        data-vg-lightbox="true"
        style={{
          background: palette.frame,
          padding: 16,
          boxShadow: "0 30px 80px -20px rgba(0,0,0,.5)",
          aspectRatio: ratio,
          /* The backdrop uses place-items:center, which content-sizes children.
             Without an explicit dimension, this container collapses (because
             image-slot inside is width:100% of a 0-width parent — circular).
             Drive sizing from HEIGHT instead: take whichever of the three caps
             is smallest, then let aspect-ratio derive the matching width. */
          height: `min(calc(100vh - 96px), calc((100vw - 96px) / ${numericRatio}), calc(1200px / ${numericRatio}))`
        }}>
        <image-slot
          id={work.id}
          shape="rect"
          placeholder={`${work.title} — drop image`}
          style={{ width: "100%", height: "100%", display: "block" }}>
        </image-slot>
      </div>
    </div>);

}

Object.assign(window, { Gallery, Lightbox, WORKS });