/* global React, THREADS, ENVIRONMENTS, COLLECTIONS, useViewport */
const { useState, useMemo, useEffect } = React;

// Routing: slugs that have a dedicated detail page. Update this list when a new
// PDP ships so both the homepage grid and the filterable index pick it up.
const COLLECTION_ROUTES = new Set([
  "gateway", "trio", "pipeline", "prisma", "caterpillar",
  "mochi", "twig", "autobahn", "cocoon", "volar", "stump-r",
  "s1", "tonne", "stump", "cup", "biggie", "platform", "strap", "picket", "pinto", "hext", "yeti",
  "rio", "pillar", "guell", "fit", "tetromino-s",
  "mass", "seed", "ivi", "homework",
  "coral", "wombat", "flatliner", "kono", "bolet", "kink", "pill",
]);
function routeForSlug(slug) {
  return COLLECTION_ROUTES.has(slug) ? slug : "gateway";
}

/* ---------- Small UI atoms ---------------------------------------------- */

function ThreadBadge({ threadKey }) {
  const t = THREADS[threadKey];
  return (
    <span style={{
      display: "inline-flex",
      alignItems: "center",
      fontSize: 9,
      letterSpacing: "0.14em",
      textTransform: "uppercase",
      fontWeight: 500,
      padding: "4px 8px 4px 7px",
      background: t.badgeBg,
      color: t.badgeText,
      borderLeft: `2px solid ${t.hex}`,
      marginRight: 6,
    }}>{t.name}</span>
  );
}

function ThreadPill({ threadKey, active, onClick, first, last, onHover }) {
  const t = THREADS[threadKey];
  return (
    <button
      onClick={onClick}
      onMouseEnter={() => onHover && onHover(threadKey)}
      onMouseLeave={() => onHover && onHover(null)}
      onFocus={() => onHover && onHover(threadKey)}
      onBlur={() => onHover && onHover(null)}
      style={{
        fontFamily: "inherit",
        fontSize: 11,
        letterSpacing: "0.14em",
        textTransform: "uppercase",
        fontWeight: 500,
        padding: "7px 14px",
        cursor: "pointer",
        background: active ? t.hex : "#f5f3ef",
        color: active ? "#ffffff" : "#1a1917",
        border: "0.5px solid " + (active ? t.hex : "#d3d1c7"),
        borderRight: last ? ("0.5px solid " + (active ? t.hex : "#d3d1c7")) : "none",
        borderRadius: 0,
        transition: "background 160ms ease, color 160ms ease, border-color 160ms ease",
      }}
    >
      {t.name}
    </button>
  );
}

function EnvPill({ envKey, active, onClick }) {
  const e = ENVIRONMENTS[envKey];
  return (
    <button
      onClick={onClick}
      style={{
        fontFamily: "inherit",
        fontSize: 11,
        letterSpacing: "0.14em",
        textTransform: "uppercase",
        fontWeight: 500,
        padding: "7px 12px",
        cursor: "pointer",
        background: active ? "#1a1917" : "#f5f3ef",
        color: active ? "#ffffff" : "#1a1917",
        border: "0.5px solid " + (active ? "#1a1917" : "#d3d1c7"),
        borderRadius: 0,
        transition: "background 160ms ease, color 160ms ease",
      }}
    >
      {e.short}
    </button>
  );
}

/* ---------- Card -------------------------------------------------------- */

function CollectionCard({ c, onClick }) {
  const [hover, setHover] = useState(false);
  return (
    <div
      onClick={onClick}
      onMouseEnter={() => setHover(true)}
      onMouseLeave={() => setHover(false)}
      style={{ cursor: onClick ? "pointer" : "default", transition: "opacity 220ms cubic-bezier(0.2,0.6,0.2,1)", opacity: hover ? 0.78 : 1 }}
    >
      <div style={{ aspectRatio: "4/5", background: "#e4e2da", position: "relative", overflow: "hidden" }}>
        {c.image ? (
          <img
            src={c.image} srcSet={window.IMG && window.IMG.srcsetFor(c.image)} sizes={window.IMG && window.IMG.sizes()}
            alt={c.name}
            loading="lazy"
            style={{ width: "100%", height: "100%", objectFit: "cover", display: "block", transition: "transform 900ms cubic-bezier(0.2,0.6,0.2,1)", transform: hover ? "scale(1.02)" : "scale(1)" }}
          />
        ) : (
          <div style={{ position: "absolute", bottom: 10, left: 12, fontSize: 9, letterSpacing: "0.16em", textTransform: "uppercase", color: "#6c6862", fontWeight: 500 }}>
            {c.name} image
          </div>
        )}
        {c.variantLabel && (
          <div style={{
            position: "absolute", top: 10, left: 10,
            display: "inline-flex", alignItems: "center", gap: 6,
            padding: "5px 9px 5px 8px",
            background: "rgba(255,255,255,0.92)",
            backdropFilter: "blur(4px)",
            fontSize: 9, letterSpacing: "0.14em", textTransform: "uppercase", fontWeight: 500, color: "#1a1917",
          }}>
            <span style={{ width: 5, height: 5, borderRadius: "50%", background: "#5a7a4d" }} />
            {c.variantLabel}
          </div>
        )}
      </div>
      <div style={{ height: "0.5px", background: "rgba(26,25,23,0.18)", marginTop: 14 }} />
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", marginTop: 12 }}>
        <div style={{ fontSize: 16, color: "#1a1917", fontWeight: 400 }}>{c.name}</div>
        <div style={{ fontSize: 11, color: "#6c6862", letterSpacing: "0.08em", textTransform: "uppercase" }}>{c.year}</div>
      </div>
      {c.tagline && (
        <div style={{ fontSize: 13, color: "#6c6862", fontWeight: 400, lineHeight: 1.45, marginTop: 6, maxWidth: "36ch" }}>
          {c.tagline}
        </div>
      )}
      <div style={{ marginTop: 10, display: "flex", flexWrap: "wrap", rowGap: 6 }}>
        {c.threads.map(tk => <ThreadBadge key={tk} threadKey={tk} />)}
      </div>
    </div>
  );
}

/* ---------- Ghost "view all" card -------------------------------------- */

function GhostCard({ remaining, onClick }) {
  return (
    <div onClick={onClick} style={{ cursor: "pointer" }}>
      <div style={{ aspectRatio: "4/5", background: "#f5f3ef", border: "0.5px dashed rgba(26,25,23,0.25)", display: "flex", alignItems: "center", justifyContent: "center", flexDirection: "column", gap: 10 }}>
        <div style={{ fontWeight: 500, fontSize: 44, letterSpacing: "-0.02em", color: "#1a1917" }}>+{remaining}</div>
        <div style={{ fontSize: 10, letterSpacing: "0.14em", textTransform: "uppercase", color: "#6c6862", fontWeight: 500 }}>More collections</div>
      </div>
      <div style={{ height: "0.5px", background: "rgba(26,25,23,0.18)", marginTop: 14 }} />
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", marginTop: 12 }}>
        <div style={{ fontSize: 14, color: "#1a1917", borderBottom: "0.5px solid #1a1917", paddingBottom: 2 }}>View all collections</div>
        <div style={{ fontFamily: "var(--font-mono)", fontSize: 14, color: "#1a1917" }}>→</div>
      </div>
    </div>
  );
}

/* ======================================================================
   CollectionGrid — used on homepage (limited, no filters)
   ====================================================================== */

function CollectionGrid({ setScreen, limit }) {
  const live = COLLECTIONS.filter(c => !c.discontinued);
  const items = limit ? live.slice(0, limit) : live;
  const vw = useViewport();
  const colsBase = vw < 560 ? 1 : vw < 860 ? 2 : vw < 1120 ? 3 : 4;
  const cols = limit ? Math.min(colsBase, items.length) : colsBase;
  const isMobile = vw < 720;
  return (
    <section style={{ padding: isMobile ? "72px 20px" : "160px max(24px, 3vw) 140px", maxWidth: 1440, margin: "0 auto" }}>
      <div style={{ display: "flex", flexDirection: isMobile ? "column" : "row", justifyContent: "space-between", alignItems: isMobile ? "flex-start" : "flex-end", gap: isMobile ? 20 : 40, marginBottom: isMobile ? 40 : 64, borderBottom: "0.5px solid rgba(26,25,23,0.18)", paddingBottom: isMobile ? 24 : 28 }}>
        <div>
          <div style={{ fontSize: 11, letterSpacing: "0.16em", textTransform: "uppercase", color: "#6c6862", fontWeight: 500, marginBottom: 10 }}>Collections</div>
          <h2 style={{ fontWeight: 500, fontSize: isMobile ? 18 : 20, lineHeight: 1.3, letterSpacing: "-0.005em", color: "#1a1917", margin: 0, maxWidth: "36ch", fontWeight: 400 }}>
            Thirty-five modular systems, specified to brief.
          </h2>
        </div>
        {limit && (
          <a onClick={() => setScreen("collections")} style={{ fontSize: 12, letterSpacing: "0.12em", textTransform: "uppercase", color: "#1a1917", fontWeight: 500, cursor: "pointer", borderBottom: "0.5px solid #1a1917", paddingBottom: 4, whiteSpace: "nowrap" }}>
            View all →
          </a>
        )}
      </div>
      <div style={{ display: "grid", gridTemplateColumns: `repeat(${cols}, 1fr)`, gap: isMobile ? 24 : 32, rowGap: isMobile ? 40 : 32 }}>
        {items.map((c) => (
          <CollectionCard key={c.slug} c={c} onClick={() => setScreen(routeForSlug(c.slug))} />
        ))}
      </div>
    </section>
  );
}

/* ======================================================================
   CollectionsIndex — the filterable index page
   Dual-axis: threads (OR within axis) + environments (OR within axis)
   Combined axes → AND
   ====================================================================== */

function CollectionsIndex({ setScreen }) {
  const [activeThreads, setActiveThreads] = useState(new Set());
  const [activeSettings, setActiveSettings] = useState(new Set());
  const [activeInstall, setActiveInstall] = useState(new Set());
  const [hoverThread, setHoverThread] = useState(null);
  const [showAll, setShowAll] = useState(false);
  const vw = useViewport();
  const isMobile = vw < 760;
  const cols = vw < 560 ? 1 : vw < 860 ? 2 : vw < 1120 ? 3 : 4;

  const toggle = (set, setter) => (key) => {
    const next = new Set(set);
    next.has(key) ? next.delete(key) : next.add(key);
    setter(next);
  };

  const SETTINGS = ["airport","hospitality","civic","education"];
  const INSTALL  = ["indoor","outdoor"];

  // Popularity order — pinned collections in display order.
  // Anything outside this list sits behind the "+ more" ghost card.
  // PdpNav reads window.PDP_ORDER (set below) so prev/next matches this sequence.
  const POPULAR = ["gateway","trio","prisma","twig","pipeline","platform","autobahn","mochi","cocoon","caterpillar","volar","stump-r","s1","tonne","stump","cup","biggie","strap","picket","pinto","hext","yeti","rio","pillar","guell","fit","tetromino-s","homework","ivi","seed","mass","bolet","coral","kink","kono","flatliner","wombat","pill"];
  const rank = (slug) => {
    const i = POPULAR.indexOf(slug);
    return i === -1 ? 999 : i;
  };

  // Merge Stump + Stump Recycled into a single card on the index. The two
  // share a body language and we want filters that match either variant
  // (e.g. "renew" → recycled, "dwell" → original) to surface one Stump card.
  // The PDPs remain separate; the merged card opens the original Stump PDP,
  // which links across to the recycled variant.
  const merged = useMemo(() => {
    const stump = COLLECTIONS.find(c => c.slug === "stump");
    const stumpR = COLLECTIONS.find(c => c.slug === "stump-r");
    if (!stump || !stumpR) return COLLECTIONS;
    const unionThreads = Array.from(new Set([...stump.threads, ...stumpR.threads]));
    const unionEnvs    = Array.from(new Set([...stump.envs, ...stumpR.envs]));
    const mergedStump = {
      ...stump,
      threads: unionThreads,
      envs: unionEnvs,
      tagline: "Cast and recycled variants — same silhouette, two materials.",
      variantLabel: "+ Recycled",
    };
    return COLLECTIONS
      .filter(c => c.slug !== "stump-r" && !c.discontinued)
      .map(c => (c.slug === "stump" ? mergedStump : c));
  }, []);

  const filtered = useMemo(() => {
    return merged.filter(c => {
      const threadMatch  = activeThreads.size === 0  || c.threads.some(t => activeThreads.has(t));
      const settingMatch = activeSettings.size === 0 || c.envs.some(e => activeSettings.has(e));
      const installMatch = activeInstall.size === 0  || c.envs.some(e => activeInstall.has(e));
      return threadMatch && settingMatch && installMatch;
    }).sort((a, b) => rank(a.slug) - rank(b.slug));
  }, [merged, activeThreads, activeSettings, activeInstall]);

  // Reset "show all" whenever filters change — each new filter state starts collapsed.
  useEffect(() => { setShowAll(false); }, [activeThreads, activeSettings, activeInstall]);

  const limit = 11;
  const visible = showAll ? filtered : filtered.slice(0, limit);
  const remaining = showAll ? 0 : Math.max(0, filtered.length - limit);

  return (
    <section style={{ padding: isMobile ? "0 20px 80px" : "0 max(24px, 3vw) 120px", maxWidth: 1440, margin: "0 auto" }}>
      <PageIntro
        eyebrow="Collections"
        title="The full range, tailored to your project."
        body="Thirty-five collections across seating, tables, and accessories. Five threads — Endure, Configure, Dwell, Renew, and Define — run through the range; pick the one your brief is asking for, or filter by setting and installation instead."
      />

      {/* ======= FILTER BAR ======= */}
      <div style={{ borderTop: "0.5px solid #d3d1c7", borderBottom: "0.5px solid #d3d1c7", padding: isMobile ? "16px 0" : "18px 0", marginBottom: isMobile ? 28 : 40 }}>
        {/* Threads row */}
        <div style={{ display: "flex", flexDirection: isMobile ? "column" : "row", alignItems: isMobile ? "flex-start" : "center", gap: isMobile ? 10 : 24, marginBottom: isMobile ? 8 : 6 }}>
          <div style={{ fontSize: 10, letterSpacing: "0.16em", textTransform: "uppercase", color: "#6c6862", fontWeight: 500, width: isMobile ? "auto" : 110, flexShrink: 0 }}>
            Thread
          </div>
          <div style={{ display: "flex", flex: 1, flexWrap: "wrap", rowGap: 0 }}>
            {Object.keys(THREADS).map((k, i, arr) => (
              <ThreadPill
                key={k}
                threadKey={k}
                active={activeThreads.has(k)}
                onClick={() => toggle(activeThreads, setActiveThreads)(k)}
                onHover={setHoverThread}
                first={i === 0}
                last={i === arr.length - 1}
              />
            ))}
          </div>
          {activeThreads.size > 0 && (
            <button onClick={() => setActiveThreads(new Set())} style={{ fontFamily: "inherit", fontSize: 10, letterSpacing: "0.14em", textTransform: "uppercase", color: "#6c6862", fontWeight: 500, background: "transparent", border: "none", cursor: "pointer", padding: 0, borderBottom: "0.5px solid #6c6862", borderRadius: 0 }}>Clear</button>
          )}
        </div>

        {/* Thread description reveal */}
        {(() => {
          const shownKey = hoverThread || (activeThreads.size === 1 ? [...activeThreads][0] : null);
          const t = shownKey ? THREADS[shownKey] : null;
          return (
            <div style={{
              display: t ? "flex" : "none",
              alignItems: "flex-start", gap: isMobile ? 10 : 16,
              paddingLeft: isMobile ? 0 : 134,
              marginTop: 6,
              marginBottom: isMobile ? 10 : 10,
              opacity: t ? 1 : 0,
              transition: "opacity 180ms ease",
              pointerEvents: "none",
            }}>
              {t && (
                <>
                  <span style={{ width: 6, height: 6, background: t.hex, display: "inline-block", flexShrink: 0, marginTop: 7 }} />
                  <span style={{ fontSize: 13, fontWeight: 500, color: "#1a1917" }}>{t.name}</span>
                  <span style={{ fontSize: 13, color: "#6c6862", fontWeight: 400, lineHeight: 1.5 }}>{t.description}</span>
                </>
              )}
            </div>
          );
        })()}

        {/* Setting row */}
        <div style={{ display: "flex", flexDirection: isMobile ? "column" : "row", alignItems: isMobile ? "flex-start" : "center", gap: isMobile ? 10 : 24, marginBottom: isMobile ? 14 : 10, marginTop: isMobile ? 14 : 14 }}>
          <div style={{ fontSize: 10, letterSpacing: "0.16em", textTransform: "uppercase", color: "#6c6862", fontWeight: 500, width: isMobile ? "auto" : 110, flexShrink: 0 }}>
            Setting
          </div>
          <div style={{ display: "flex", gap: 8, flex: 1, flexWrap: "wrap" }}>
            {SETTINGS.map(k => (
              <EnvPill key={k} envKey={k} active={activeSettings.has(k)} onClick={() => toggle(activeSettings, setActiveSettings)(k)} />
            ))}
          </div>
          {activeSettings.size > 0 && (
            <button onClick={() => setActiveSettings(new Set())} style={{ fontFamily: "inherit", fontSize: 10, letterSpacing: "0.14em", textTransform: "uppercase", color: "#6c6862", fontWeight: 500, background: "transparent", border: "none", cursor: "pointer", padding: 0, borderBottom: "0.5px solid #6c6862", borderRadius: 0 }}>Clear</button>
          )}
        </div>

        {/* Installation row */}
        <div style={{ display: "flex", flexDirection: isMobile ? "column" : "row", alignItems: isMobile ? "flex-start" : "center", gap: isMobile ? 10 : 24 }}>
          <div style={{ fontSize: 10, letterSpacing: "0.16em", textTransform: "uppercase", color: "#6c6862", fontWeight: 500, width: isMobile ? "auto" : 110, flexShrink: 0 }}>
            Installation
          </div>
          <div style={{ display: "flex", gap: 8, flex: 1, flexWrap: "wrap" }}>
            {INSTALL.map(k => (
              <EnvPill key={k} envKey={k} active={activeInstall.has(k)} onClick={() => toggle(activeInstall, setActiveInstall)(k)} />
            ))}
          </div>
          {activeInstall.size > 0 && (
            <button onClick={() => setActiveInstall(new Set())} style={{ fontFamily: "inherit", fontSize: 10, letterSpacing: "0.14em", textTransform: "uppercase", color: "#6c6862", fontWeight: 500, background: "transparent", border: "none", cursor: "pointer", padding: 0, borderBottom: "0.5px solid #6c6862", borderRadius: 0 }}>Clear</button>
          )}
        </div>
      </div>

      {/* ======= COUNT ======= */}
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", marginBottom: 32 }}>
        <div style={{ fontSize: 13, color: "#1a1917" }}>
          <b style={{ fontWeight: 500 }}>{filtered.length}</b>
          <span style={{ color: "#6c6862" }}> of {merged.length} collections</span>
          {(activeThreads.size + activeSettings.size + activeInstall.size) > 0 && (
            <span style={{ color: "#6c6862" }}>
              {" · "}
              {[
                [...activeThreads].map(t => THREADS[t].name).join(", "),
                [...activeSettings].map(e => ENVIRONMENTS[e].short).join(", "),
                [...activeInstall].map(e => ENVIRONMENTS[e].short).join(", "),
              ].filter(Boolean).join(" · ")}
            </span>
          )}
        </div>
      </div>

      {/* ======= GRID ======= */}
      {filtered.length === 0 ? (
        <div style={{ padding: "80px 0", borderTop: "0.5px solid #d3d1c7", textAlign: "center", color: "#6c6862", fontSize: 14 }}>
          No collections match this combination. Remove a filter to broaden the result.
        </div>
      ) : (
        <div style={{ display: "grid", gridTemplateColumns: `repeat(${cols}, 1fr)`, gap: isMobile ? 24 : 32, rowGap: isMobile ? 40 : 56 }}>
          {visible.map(c => (
            <CollectionCard key={c.slug} c={c} onClick={() => setScreen(routeForSlug(c.slug))} />
          ))}
          {remaining > 0 && (
            <GhostCard remaining={remaining} onClick={() => setShowAll(true)} />
          )}
        </div>
      )}
    </section>
  );
}

window.CollectionGrid = CollectionGrid;
window.CollectionsIndex = CollectionsIndex;
window.ThreadBadge = ThreadBadge;
// PdpNav reads this so prev/next on a PDP follows the same order the user
// just browsed on the Collections page.
window.PDP_ORDER = ["gateway","trio","prisma","twig","pipeline","platform","autobahn","mochi","cocoon","caterpillar","volar","s1","tonne","stump","cup","biggie","strap","picket","pinto","hext","yeti","rio","pillar","guell","fit","tetromino-s","homework","ivi","seed","mass","bolet","coral","kink","kono","flatliner","wombat","pill"];
