const ARCHIVE_ITEMS = [
  { id: "jd", medium: "film", mlabel: "Film", title: "Jeanne Dielman", by: "Chantal Akerman", year: "1975",
    tone: "sienna", rating: 5, date: "22 May", reviewTitle: "Jeanne Dielman",
    review: "Three days, one kitchen, and the most radical thing I've ever watched happen to ordinary time. It rewires what you think cinema is allowed to be patient about.", lb: "letterboxd.com/Mulla759" },
  { id: "we", medium: "book", mlabel: "Book", title: "Weather", by: "Jenny Offill", year: "2021",
    tone: "pine", rating: 4, date: "this week", reviewTitle: "Weather",
    review: "Fragments that accrue into dread and tenderness. I keep a note of half its sentences; they read like things I almost thought first.", lb: "letterboxd.com/Mulla759" },
  { id: "lc", medium: "film", mlabel: "Film", title: "La Chimera", by: "Alice Rohrwacher", year: "2024",
    tone: "rose", rating: 4.5, date: "09 May", reviewTitle: "La Chimera",
    review: "Grave-robbers and ghosts shot like a faded postcard. Rohrwacher finds the sacred in the second-hand. Stayed with me for days.", lb: "letterboxd.com/Mulla759" },
  { id: "ts", medium: "music", mlabel: "Music", title: "Two Star", by: "Mk.gee", year: "2024",
    tone: "ink", rating: "repeat", date: "today", reviewTitle: "Two Star & the Dream Police",
    review: "Sounds like a memory of a song you can't place. On repeat for a month now — the production is a whole argument about restraint.", lb: "last.fm/user/Mulla759" },
  { id: "ou", medium: "book", mlabel: "Book", title: "Outline", by: "Rachel Cusk", year: "2014",
    tone: "cool", rating: 5, date: "02 May", reviewTitle: "Outline",
    review: "A novel that listens. Cusk dissolves the narrator until the book becomes a room other people talk in. Quietly devastating.", lb: "letterboxd.com/Mulla759" },
];

const ARCHIVE_TONES = {
  sienna: "linear-gradient(150deg,#a9683a,#5e3413)", pine: "linear-gradient(150deg,#3f6b4d,#1d3a28)",
  rose: "linear-gradient(150deg,#b07f6e,#6e4a40)", ink: "linear-gradient(150deg,#3a3630,#141210)",
  cool: "linear-gradient(150deg,#7c828b,#474d57)", warm: "linear-gradient(150deg,#c4bdac,#8f876f)",
};

function PosterCard({ item, onOpen }) {
  const yr = item.year ? ` · '${String(item.year).slice(-2)}` : "";
  return (
    <div onClick={() => onOpen(item)}
      style={{ flex: "0 0 168px", scrollSnapAlign: "start", cursor: "pointer", transition: "transform 320ms var(--ease-cinematic)" }}
      onMouseEnter={e => e.currentTarget.style.transform = "translateY(-5px)"}
      onMouseLeave={e => e.currentTarget.style.transform = "none"}>
      <div style={{ position: "relative", aspectRatio: "3/4", borderRadius: 2, overflow: "hidden",
        background: ARCHIVE_TONES[item.tone] || ARCHIVE_TONES.warm, display: "flex", alignItems: "center", justifyContent: "center" }}>
        {item.poster && (
          <img src={item.poster} alt={item.title} loading="lazy" decoding="async"
            style={{ position: "absolute", inset: 0, width: "100%", height: "100%", objectFit: "cover" }} />
        )}
        <span className="grain-field" />
        <span style={{ position: "absolute", top: 9, left: 9, fontFamily: "var(--font-micro)", fontSize: 8,
          letterSpacing: "0.12em", textTransform: "uppercase", color: "rgba(255,255,255,0.92)" }}>{item.date}</span>
        {!item.poster && (
          <span style={{ position: "relative", zIndex: 1, color: "rgba(255,255,255,0.92)" }}>
            <Pictograph kind={item.medium === "music" ? "vinyl" : item.medium} size={40} color="rgba(255,255,255,0.92)" /></span>
        )}
        <span style={{ position: "absolute", bottom: 9, left: 9, fontFamily: "var(--font-micro)", fontSize: 7,
          letterSpacing: "0.18em", textTransform: "uppercase", color: "rgba(255,255,255,0.72)" }}>{item.mlabel}{yr}</span>
      </div>
      <div style={{ marginTop: 9 }}>
        <div style={{ fontFamily: "var(--font-display)", fontWeight: 300, fontSize: 18, letterSpacing: "-0.02em", lineHeight: 0.98, color: "var(--paper-on-ink)" }}>{item.title}</div>
        {item.by && <div style={{ fontFamily: "var(--font-body)", fontSize: 10, color: "var(--paper-on-ink-2)", marginTop: 2 }}>{item.by}</div>}
        <div style={{ marginTop: 7 }}>
          {item.rating === "repeat"
            ? <span style={{ display: "inline-flex", alignItems: "center", gap: 8 }}><Equalizer h={13} bars={[6, 13, 9, 12]} /><Micro size={8} color="var(--vermilion)">on repeat</Micro></span>
            : item.rating != null
              ? <span className="stars-pop"><Stars value={item.rating} hoverPop /></span>
              : <Micro size={8} color="var(--paper-on-ink-2)">logged</Micro>}
        </div>
      </div>
    </div>
  );
}

const REVIEW_LIMIT = 260;
function clampReview(text, limit = REVIEW_LIMIT) {
  if (!text) return { text: "", truncated: false };
  if (text.length <= limit) return { text, truncated: false };
  let cut = text.slice(0, limit);
  const lastSpace = cut.lastIndexOf(" ");
  if (lastSpace > limit * 0.6) cut = cut.slice(0, lastSpace);
  return { text: cut.replace(/[\s,.;:!?\-–—]+$/, "") + "…", truncated: true };
}

function ReviewModal({ item, onClose }) {
  if (!item) return null;
  const showReadMore = item.medium !== "music";
  const clamped = clampReview(item.review);
  return (
    <div onClick={onClose} style={{ position: "fixed", inset: 0, zIndex: 100, background: "rgba(20,18,15,0.62)",
      display: "flex", alignItems: "center", justifyContent: "center", padding: 24, overscrollBehavior: "contain", backdropFilter: "blur(2px)" }}>
      <div onClick={e => e.stopPropagation()} style={{ background: "var(--paper-bright)", width: "min(720px, 96vw)",
        maxHeight: "calc(100dvh - 48px)", overflow: "hidden",
        display: "grid", gridTemplateColumns: "minmax(0,0.8fr) minmax(0,1fr)", boxShadow: "0 30px 80px rgba(20,18,15,0.4)" }}>
        <div style={{ minHeight: 320, position: "relative", overflow: "hidden", background: "var(--earth-espresso)" }}>
          {item.poster
            ? <>
                <img src={item.poster} alt={item.title} loading="lazy" decoding="async"
                  style={{ position: "absolute", inset: 0, width: "100%", height: "100%", objectFit: "cover", objectPosition: "center top" }} />
                <span className="grain-field" />
              </>
            : <Plate ratio="3/4" tone={item.tone} frame={`${item.mlabel} · ${item.year}`} style={{ height: "100%", borderRadius: 0 }} />}
        </div>
        <div style={{ padding: "30px 32px", position: "relative", display: "flex", flexDirection: "column", minHeight: 0 }}>
          <button onClick={onClose} style={{ position: "absolute", top: 16, right: 18, background: "none", border: "none",
            fontFamily: "var(--font-micro)", fontSize: 16, color: "var(--ink-3)", lineHeight: 1 }}>×</button>
          <Micro size={9} color="var(--vermilion)" style={{ fontWeight: 700 }}>Review · {item.mlabel}</Micro>
          <div style={{ fontFamily: "var(--font-annotation)", fontSize: 38, color: "var(--vermilion)", lineHeight: 0.95, margin: "10px 0 6px" }}>{item.reviewTitle}</div>
          <Micro size={9} color="var(--ink-3)">{[item.by, item.year, item.date].filter(Boolean).join(" · ")}</Micro>
          <div style={{ margin: "14px 0 18px" }}>
            {item.rating === "repeat"
              ? <span style={{ display: "inline-flex", alignItems: "center", gap: 8 }}><Equalizer h={15} /><Micro size={9} color="var(--vermilion)">on repeat</Micro></span>
              : item.rating != null ? <Stars value={item.rating} /> : <Micro size={9} color="var(--ink-4)">Logged · {item.date}</Micro>}
          </div>
          {item.review
            ? <p style={{ fontFamily: "var(--font-body)", fontSize: 15, lineHeight: 1.55, color: "var(--ink-2)", marginBottom: clamped.truncated ? 12 : 24 }}>
                {clamped.text}{clamped.truncated && <span style={{ color: "var(--ink-4)", fontStyle: "italic" }}> continued on Letterboxd</span>}
              </p>
            : <p style={{ fontFamily: "var(--font-body)", fontStyle: "italic", fontSize: 14, lineHeight: 1.55, color: "var(--ink-3)", marginBottom: 24 }}>Logged without a written note.</p>}
          {showReadMore && (
            <div style={{ marginTop: "auto", borderTop: "1px solid var(--rule)", paddingTop: 14 }}>
              <a href={"https://" + item.lb} target="_blank" rel="noreferrer" style={{ textDecoration: "none" }}>
                <ArrowLink dir="↗">{clamped.truncated ? "Read the full review on Letterboxd" : "Read more on Letterboxd"}</ArrowLink></a>
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

function ScrobbleFeed() {
  const rows = [
    ["Alex G", "Runner", "14:02 · today"], ["Blood Orange", "Charcoal Baby", "13:48 · today"],
    ["Sade", "Cherish the Day", "13:20 · today"], ["Frank Ocean", "Ivy", "12:55 · today"],
    ["Nilüfer Yanya", "Stabilise", "23:10 · 28 May"],
  ];
  const Row = ([a, t, w], i) => (
    <div key={i} style={{ display: "grid", gridTemplateColumns: "1fr auto", gap: 12, alignItems: "baseline", padding: "8px 0", borderBottom: "1px solid var(--rule-on-ink)" }}>
      <span style={{ fontFamily: "var(--font-micro)", fontSize: 11, letterSpacing: "0.03em", color: "var(--paper-on-ink-2)" }}>
        <b style={{ color: "var(--paper-on-ink)", fontWeight: 400 }}>{a}</b> — {t}</span>
      <Micro size={8} color="var(--paper-on-ink-2)">{w}</Micro>
    </div>
  );
  return (
    <div style={{ height: 132, overflow: "hidden", borderTop: "1px solid var(--rule-on-ink)",
      WebkitMaskImage: "linear-gradient(180deg, transparent, #000 14%, #000 82%, transparent)",
      maskImage: "linear-gradient(180deg, transparent, #000 14%, #000 82%, transparent)" }}>
      <div style={{ animation: "rise 16s linear infinite" }}>{rows.map(Row)}{rows.map(Row)}</div>
    </div>
  );
}

function LiveRail() {
  return (
    <aside style={{ display: "flex", flexDirection: "column", gap: 34 }}>
      <div>
        <div style={{ display: "flex", alignItems: "center", gap: 7, marginBottom: 16 }}>
          <span style={{ width: 6, height: 6, borderRadius: "50%", background: "var(--vermilion)", animation: "pulse 1.4s var(--ease-soft) infinite" }} />
          <Micro size={9} color="var(--vermilion)" style={{ fontWeight: 700 }}>Now playing</Micro>
        </div>
        <div style={{ display: "grid", gridTemplateColumns: "auto 1fr auto", gap: 16, alignItems: "center" }}>
          <VinylSpinner size={52} />
          <div>
            <div style={{ fontFamily: "var(--font-display)", fontWeight: 300, fontSize: 24, letterSpacing: "-0.02em", lineHeight: 1, color: "var(--paper-on-ink)" }}>Are You Looking Up</div>
            <div style={{ fontFamily: "var(--font-body)", fontSize: 11, color: "var(--paper-on-ink-2)", marginTop: 4 }}>Mk.gee</div>
          </div>
          <Equalizer />
        </div>
        <div style={{ height: 2, background: "var(--rule-on-ink)", margin: "16px 0 6px", position: "relative", overflow: "hidden" }}>
          <span style={{ position: "absolute", left: 0, top: 0, bottom: 0, width: "46%", background: "var(--paper-on-ink)" }} />
        </div>
        <div style={{ display: "flex", justifyContent: "space-between" }}>
          <Micro size={8} color="var(--paper-on-ink-2)">1:42</Micro><Micro size={8} color="var(--paper-on-ink-2)">Last.fm · scrobbling</Micro><Micro size={8} color="var(--paper-on-ink-2)">3:08</Micro>
        </div>
      </div>
      <div>
        <div style={{ display: "flex", alignItems: "center", gap: 7, marginBottom: 8 }}>
          <span style={{ width: 5, height: 5, borderRadius: "50%", background: "var(--paper-on-ink-2)" }} />
          <Micro size={9} color="var(--paper-on-ink-2)">Recently scrobbled</Micro>
        </div>
        <ScrobbleFeed />
      </div>
    </aside>
  );
}

function Archive() {
  const [sel, setSel] = React.useState(null);
  const [items, setItems] = React.useState(ARCHIVE_ITEMS);
  const reelRef = React.useRef(null);
  React.useEffect(() => {
    let alive = true;
    fetch("data/letterboxd.json")
      .then(r => (r.ok ? r.json() : Promise.reject(r.status)))
      .then(d => { if (alive && d && Array.isArray(d.items) && d.items.length) setItems(d.items); })
      .catch(() => {});
    return () => { alive = false; };
  }, []);
  React.useEffect(() => {
    if (!sel) return;
    const prev = document.body.style.overflow;
    document.body.style.overflow = "hidden";
    return () => { document.body.style.overflow = prev; };
  }, [sel]);

  const nudge = (dir) => {
    const el = reelRef.current;
    if (el) el.scrollBy({ left: dir * 340, behavior: "smooth" });
  };
  const arrow = {
    width: 30, height: 30, lineHeight: 1, fontSize: 14, background: "transparent",
    border: "1px solid var(--rule-on-ink)", color: "var(--paper-on-ink)", cursor: "pointer",
    transition: "border-color 260ms var(--ease-soft), color 260ms var(--ease-soft)",
  };

  return (
    <section id="archive" className="section" style={{ background: "var(--paper-ink)", color: "var(--paper-on-ink)" }}>
      <Kicker>— Recently rated, from Letterboxd</Kicker>
      <h2 style={{ fontFamily: "var(--font-display)", fontWeight: 700, fontSize: "clamp(3.4rem,9vw,7rem)",
        lineHeight: 0.88, letterSpacing: "-0.045em", color: "var(--paper-on-ink)", margin: "8px 0 0" }}>Archive</h2>

      <div style={{ display: "flex", flexWrap: "wrap", justifyContent: "space-between", alignItems: "flex-end",
        gap: 24, marginTop: 18, marginBottom: "clamp(40px,6vw,72px)" }}>
        <p style={{ fontFamily: "var(--font-body)", fontSize: "clamp(1rem,1.2vw,1.15rem)", lineHeight: 1.5,
          color: "var(--paper-on-ink-2)", maxWidth: "44ch", margin: 0 }}>
          Everything I've been watching, reading and hearing — an evolving log of the non-suffering stuff.
        </p>
        <Micro size={10} color="var(--paper-on-ink-2)">412 films · updated sep 29</Micro>
      </div>

      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 14 }}>
        <Micro size={10} color="var(--paper-on-ink-2)">Recently rated, from Letterboxd</Micro>
        <div style={{ display: "flex", gap: 8 }}>
          <button aria-label="Scroll left" onClick={() => nudge(-1)} style={arrow}
            onMouseEnter={e => { e.currentTarget.style.color = "var(--vermilion)"; e.currentTarget.style.borderColor = "var(--vermilion)"; }}
            onMouseLeave={e => { e.currentTarget.style.color = "var(--paper-on-ink)"; e.currentTarget.style.borderColor = "var(--rule-on-ink)"; }}>‹</button>
          <button aria-label="Scroll right" onClick={() => nudge(1)} style={arrow}
            onMouseEnter={e => { e.currentTarget.style.color = "var(--vermilion)"; e.currentTarget.style.borderColor = "var(--vermilion)"; }}
            onMouseLeave={e => { e.currentTarget.style.color = "var(--paper-on-ink)"; e.currentTarget.style.borderColor = "var(--rule-on-ink)"; }}>›</button>
        </div>
      </div>

      <div className="reel" ref={reelRef} style={{ display: "flex", gap: 16, overflowX: "auto",
        paddingBottom: 14, scrollSnapType: "x proximity", marginBottom: "clamp(40px,6vw,72px)" }}>
        {items.map(it => <PosterCard key={it.id} item={it} onOpen={setSel} />)}
      </div>

      <Reveal>
        <div className="cols cols--mainrail">
          <LiveRail />
          <a href="https://letterboxd.com/Mulla759/" target="_blank" rel="noreferrer"
            style={{ textDecoration: "none", display: "block", border: "1px solid var(--rule-strong)", padding: 18,
              background: "var(--paper-bright)", color: "var(--ink)", alignSelf: "start" }}>
            <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
              <div>
                <Micro size={9} color="var(--vermilion)">Letterboxd</Micro>
                <div style={{ fontFamily: "var(--font-display)", fontWeight: 300, fontSize: 22, letterSpacing: "-0.02em", color: "var(--ink)", marginTop: 4 }}>@Mulla759</div>
              </div>
              <span style={{ fontFamily: "var(--font-micro)", fontSize: 18, color: "var(--vermilion)" }}>↗</span>
            </div>
            <div style={{ display: "flex", gap: 22, marginTop: 16, borderTop: "1px solid var(--rule)", paddingTop: 14 }}>
              {[["412", "films"], ["38", "this year"], ["91", "lists"]].map(([n, l]) => (
                <div key={l}>
                  <div style={{ fontFamily: "var(--font-micro)", fontSize: 16, color: "var(--ink)" }}>{n}</div>
                  <Micro size={8} color="var(--ink-4)">{l}</Micro>
                </div>
              ))}
            </div>
          </a>
        </div>
      </Reveal>

      <ReviewModal item={sel} onClose={() => setSel(null)} />
    </section>
  );
}

Object.assign(window, { Archive });
