/* global React, Icon, Eyebrow, Serif, DATA,
   LabSection, LabField, LabTag, LabContext, useLab */
/* =====================================================================
   THE STORY LAB — interaction sections (the working spine).
   Reuses the descent's interaction grammar: the fork (futures), draggable
   ranking (cruxes), the lens switcher (lenses), the assumptions grid.
   Every [her turn] surface is a visibly empty, editable input; every [seed]
   is pre-filled but overwritable. Nothing resolves a choice she hasn't made.
   ===================================================================== */
const { useState: uP, useRef: uPR, useContext: uPCx } = React;

/* ---- drag grip glyph ---------------------------------------------- */
function Grip() {
  return (
    <svg width="10" height="16" viewBox="0 0 10 16" aria-hidden="true" style={{ display: "block", color: "var(--fg2)" }}>
      {[3, 8, 13].map((y) => [2, 8].map((x) => <circle key={x + "-" + y} cx={x} cy={y} r="1.25" fill="currentColor" />))}
    </svg>
  );
}

/* ---- reusable draggable ranker ------------------------------------ */
function Ranker({ labKey, items, renderItem }) {
  const ids = items.map((i) => i.id);
  const [order, setOrder] = useLab(labKey, ids);
  const clean = (Array.isArray(order) ? order : ids).filter((x) => ids.includes(x));
  const full = clean.concat(ids.filter((x) => !clean.includes(x)));
  const dragId = uPR(null);
  const [over, setOver] = uP(null);
  const [dragging, setDragging] = uP(null);

  const move = (fromId, toId) => {
    if (!fromId || fromId === toId) return;
    const a = full.filter((x) => x !== fromId);
    const idx = a.indexOf(toId);
    a.splice(idx < 0 ? a.length : idx, 0, fromId);
    setOrder(a);
  };

  return (
    <div style={{ border: "1px solid var(--ink)" }}>
      {full.map((id, i) => {
        const it = items.find((x) => x.id === id);
        if (!it) return null;
        return (
          <div key={id} draggable
            onDragStart={(e) => {
              if (e.target.closest && e.target.closest("button, input, textarea")) { e.preventDefault(); return; }
              dragId.current = id; setDragging(id); e.dataTransfer.effectAllowed = "move";
              try { e.dataTransfer.setData("text/plain", id); } catch (_) {}
            }}
            onDragOver={(e) => { e.preventDefault(); if (over !== id) setOver(id); }}
            onDragEnd={() => { dragId.current = null; setDragging(null); setOver(null); }}
            onDrop={(e) => { e.preventDefault(); move(dragId.current, id); setOver(null); setDragging(null); }}
            className={over === id && dragging !== id ? "lab-drag-over" : ""}
            style={{ display: "flex", alignItems: "flex-start", gap: 14, padding: "14px 16px",
              borderBottom: i < full.length - 1 ? "1px solid var(--fog)" : "none",
              background: dragging === id ? "var(--bone)" : "transparent",
              opacity: dragging === id ? 0.5 : 1 }}>
            <span className="lab-grip" style={{ display: "inline-flex", alignItems: "center", gap: 9,
              paddingTop: 2, flex: "0 0 auto" }}>
              <Grip />
              <span style={{ fontFamily: "var(--font-mono)", fontSize: 14, color: "var(--signal)",
                width: 15, textAlign: "center" }}>{i + 1}</span>
            </span>
            <div style={{ flex: 1, minWidth: 0 }}>{renderItem(it, i)}</div>
          </div>
        );
      })}
    </div>
  );
}

function RankHint() {
  return (
    <div style={{ display: "flex", alignItems: "center", gap: 10, marginBottom: 14,
      fontFamily: "var(--font-mono)", fontSize: 10, letterSpacing: "0.12em", textTransform: "uppercase",
      color: "var(--fg2)" }}>
      <Grip /> Drag to rank
    </div>
  );
}

/* ---- seeded rank item with a what / why / example reveal ---------- */
function DetailBlock({ label, text, accent }) {
  if (!text) return null;
  return (
    <div style={{ borderLeft: `2px solid ${accent ? "var(--signal)" : "var(--fog)"}`, paddingLeft: 14 }}>
      <div style={{ fontFamily: "var(--font-mono)", fontSize: 9, letterSpacing: "0.14em",
        textTransform: "uppercase", color: accent ? "var(--signal)" : "var(--fg2)", marginBottom: 5 }}>{label}</div>
      <div style={{ fontSize: 14, lineHeight: 1.5, color: "var(--ash)" }}>{text}</div>
    </div>
  );
}
function RankDetail({ item }) {
  const [open, setOpen] = uP(false);
  const has = item.what || item.why || item.example;
  return (
    <div style={{ paddingTop: 2 }}>
      <div style={{ fontSize: 16, lineHeight: 1.45, color: "var(--ink)", fontWeight: 500 }}>{item.text}</div>
      {item.flag && (
        <div style={{ display: "inline-flex", alignItems: "center", gap: 8, marginTop: 9,
          fontFamily: "var(--font-mono)", fontSize: 10.5, letterSpacing: "0.04em", color: "var(--signal)",
          border: "1px solid var(--signal)", padding: "4px 9px" }}>
          High uncertainty · {item.flag}
        </div>
      )}
      {has && (
        <div style={{ marginTop: 10 }}>
          <button onClick={() => setOpen(!open)} className="focus-ring" draggable={false} style={{
            all: "unset", cursor: "pointer", display: "inline-flex", alignItems: "center", gap: 9,
            fontFamily: "var(--font-mono)", fontSize: 10, letterSpacing: "0.12em", textTransform: "uppercase",
            color: "var(--fg2)" }}>
            <span style={{ width: 16, height: 16, border: "1px solid var(--fg2)", display: "inline-flex",
              alignItems: "center", justifyContent: "center" }}><Icon name={open ? "minus" : "plus"} size={10} /></span>
            {open ? "Hide" : "What it is · why · example"}
          </button>
          <div style={{ display: "grid", gridTemplateRows: open ? "1fr" : "0fr",
            transition: "grid-template-rows var(--dur) var(--ease)" }}>
            <div style={{ overflow: "hidden", minHeight: 0 }}>
              <div style={{ paddingTop: 14, display: "flex", flexDirection: "column", gap: 12 }}>
                <DetailBlock label="What it is" text={item.what} />
                <DetailBlock label="Why it matters" text={item.why} />
                <DetailBlock label="Example" text={item.example} accent />
              </div>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

/* ============================ STAGE 02 · vehicle fork =============== */
function VehicleFork({ data }) {
  const [choice, setChoice] = useLab("vehicles.choice", "");
  const chosen = data.options.find((o) => o.id === choice);
  const cellBorder = (i) => ({
    borderRight: "1px solid var(--ink)", borderBottom: "1px solid var(--ink)",
  });
  return (
    <LabSection data={data} spine>
      <p style={{ fontFamily: "var(--font-mono)", fontSize: 11, letterSpacing: "0.06em",
        color: "var(--signal)", textTransform: "uppercase", margin: "0 0 20px" }}>{data.hold}</p>

      <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(272px,1fr))",
        borderTop: "1px solid var(--ink)", borderLeft: "1px solid var(--ink)" }} className="lab-vehicles">
        {data.options.map((o, i) => {
          const on = choice === o.id;
          return (
            <div key={o.id} style={{ ...cellBorder(i), padding: "22px 20px 24px", display: "flex",
              flexDirection: "column", background: on ? "rgba(214,74,31,0.055)" : "transparent",
              transition: "background var(--dur) var(--ease)" }}>
              <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", gap: 10 }}>
                <span style={{ fontFamily: "var(--font-mono)", fontSize: 11, letterSpacing: "0.12em",
                  color: on ? "var(--signal)" : "var(--fg2)" }}>VEHICLE {o.n}</span>
                <button onClick={() => setChoice(on ? "" : o.id)} className="focus-ring" style={{
                  all: "unset", cursor: "pointer", display: "inline-flex", alignItems: "center", gap: 7,
                  fontFamily: "var(--font-mono)", fontSize: 9.5, letterSpacing: "0.12em", textTransform: "uppercase",
                  padding: "5px 9px", whiteSpace: "nowrap",
                  border: `1px solid ${on ? "var(--signal)" : "var(--fog)"}`,
                  background: on ? "var(--signal)" : "transparent",
                  color: on ? "var(--paper)" : "var(--ash)" }}>
                  {on ? <><Icon name="check" size={11} /> Leaning</> : "Lean toward this"}
                </button>
              </div>
              <div style={{ fontFamily: "var(--font-sans)", fontWeight: 700, fontSize: 20,
                letterSpacing: "-0.02em", lineHeight: 1.12, margin: "16px 0 12px", color: "var(--ink)" }}>{o.label}</div>
              <div style={{ fontSize: 14.5, lineHeight: 1.5, color: "var(--ash)" }}>{o.what}</div>
              <div style={{ fontFamily: "var(--font-serif)", fontStyle: "italic", fontSize: 17,
                lineHeight: 1.35, color: "var(--ink)", marginTop: 12 }}>{o.who}</div>

              <div style={{ marginTop: 18, paddingTop: 16, borderTop: "1px solid var(--fog)" }}>
                <div style={{ fontFamily: "var(--font-mono)", fontSize: 9.5, letterSpacing: "0.1em",
                  textTransform: "uppercase", color: "var(--fg2)", marginBottom: 8 }}>Starting read</div>
                <div style={{ fontSize: 13.5, lineHeight: 1.5, color: "var(--ash)" }}>{o.seedRead}</div>
              </div>

              <div style={{ marginTop: 18 }}>
                <div style={{ marginBottom: 8 }}><LabTag kind="turn" /></div>
                <LabField id={"vehicles.read." + o.id} kind="turn"
                  placeholder={data.readPlaceholder} minRows={2} />
              </div>
            </div>
          );
        })}
      </div>

      {/* decision prompt (always live) */}
      <div style={{ borderLeft: "3px solid var(--signal)", padding: "6px 0 6px 22px", marginTop: 30,
        maxWidth: "58ch" }}>
        <div style={{ fontFamily: "var(--font-mono)", fontSize: 10, letterSpacing: "0.14em",
          textTransform: "uppercase", color: "var(--signal)", marginBottom: 10 }}>The decision prompt</div>
        <div style={{ fontFamily: "var(--font-serif)", fontStyle: "italic", fontSize: "clamp(20px,2.4vw,27px)",
          lineHeight: 1.28, color: "var(--ink)" }}>{data.prompt}</div>
      </div>

      <div style={{ marginTop: 20, minHeight: 26 }}>
        {chosen ? (
          <div style={{ color: "var(--ash)", fontSize: 15, lineHeight: 1.5, maxWidth: "60ch" }}>
            Leaning toward <span style={{ color: "var(--ink)", fontWeight: 600 }}>{chosen.label}</span>. Held, not
            decided. The story follows the vehicle, not the other way around. Change it whenever the evidence does.
          </div>
        ) : (
          <div style={{ color: "var(--fg2)", fontSize: 15, lineHeight: 1.5, maxWidth: "60ch" }}>
            Nothing is selected. Write a read for each, then lean toward one when the fastest path to proof is clear.
          </div>
        )}
      </div>
    </LabSection>
  );
}

/* ============================ STAGE 04 · belief ranker ============= */
function BeliefRanker({ data }) {
  return (
    <LabSection data={data}>
      <RankHint />
      <Ranker labKey="beliefs.order" items={data.items} renderItem={(it) => (
        it.turn ? (
          <div style={{ display: "flex", alignItems: "flex-start", gap: 12 }}>
            <div style={{ flex: 1, minWidth: 0 }}>
              <LabField id={"beliefs.text." + it.id} kind="turn" placeholder={it.placeholder} minRows={1} />
            </div>
            <div style={{ flex: "0 0 auto", paddingTop: 6 }}><LabTag kind="turn" /></div>
          </div>
        ) : (
          <RankDetail item={it} />
        )
      )} />
      <div style={{ marginTop: 14, fontFamily: "var(--font-mono)", fontSize: 11, letterSpacing: "0.06em",
        color: "var(--fg2)", display: "flex", alignItems: "center", gap: 8 }}>
        <span style={{ color: "var(--signal)" }}>01</span> sets the opening of any deck.
      </div>
    </LabSection>
  );
}

/* ============================ STAGE 05 · audience doorways ========= */
function AudienceDoorways({ data }) {
  const [active, setActive] = uP(data.doors[0].id);
  const door = data.doors.find((d) => d.id === active) || data.doors[0];
  return (
    <LabSection data={data}>
      <div style={{ display: "grid", gridTemplateColumns: "minmax(0,0.82fr) minmax(0,1.18fr)",
        gap: "clamp(20px,4vw,52px)", alignItems: "start" }} className="lens-grid">
        {/* door selector */}
        <div>
          <div style={{ border: "1px solid var(--ink)" }}>
            {data.doors.map((d, i) => {
              const on = d.id === active;
              return (
                <button key={d.id} onClick={() => setActive(d.id)} className="focus-ring" style={{
                  all: "unset", cursor: "pointer", display: "block", width: "100%", boxSizing: "border-box",
                  padding: "14px 16px", borderBottom: i < data.doors.length - 1 ? "1px solid var(--fog)" : "none",
                  background: on ? "var(--ink)" : "transparent", color: on ? "var(--paper)" : "var(--ink)",
                  transition: "background var(--dur-fast) var(--ease)" }}>
                  <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", gap: 10 }}>
                    <span>
                      <span style={{ fontFamily: "var(--font-mono)", fontSize: 10, letterSpacing: "0.12em",
                        color: on ? "rgba(242,240,235,0.55)" : "var(--fg2)", marginRight: 10 }}>0{i + 1}</span>
                      <span style={{ fontWeight: 700, fontSize: 15.5, letterSpacing: "-0.01em" }}>{d.label}</span>
                    </span>
                    {on && <Icon name="arrowRight" size={15} />}
                  </div>
                  <div style={{ fontFamily: "var(--font-mono)", fontSize: 9, letterSpacing: "0.1em",
                    textTransform: "uppercase", marginTop: 6,
                    color: d.priority ? "var(--signal)" : (on ? "rgba(242,240,235,0.5)" : "var(--fg2)") }}>{d.tag}</div>
                </button>
              );
            })}
          </div>
          <div style={{ marginTop: 12, fontFamily: "var(--font-mono)", fontSize: 10.5, letterSpacing: "0.04em",
            color: "var(--fg2)", lineHeight: 1.5 }}>
            Design for the first door first. Clate before anyone else.
          </div>
        </div>

        {/* the door's three fields */}
        <div>
          <div style={{ borderLeft: `3px solid ${door.priority ? "var(--signal)" : "var(--ink)"}`,
            padding: "2px 0 2px 18px", marginBottom: 26 }}>
            <div style={{ fontFamily: "var(--font-mono)", fontSize: 10, letterSpacing: "0.14em",
              textTransform: "uppercase", color: door.priority ? "var(--signal)" : "var(--fg2)", marginBottom: 8 }}>
              {door.tag}{door.priority ? " · priority" : ""}
            </div>
            <div style={{ fontSize: 16, lineHeight: 1.5, color: "var(--ink)", maxWidth: "48ch" }}>{door.note}</div>
          </div>
          <div style={{ display: "flex", flexDirection: "column", gap: 24 }}>
            {data.fields.map((f) => (
              <LabField key={f.id} id={"doorways." + active + "." + f.id} kind="turn"
                label={f.label} placeholder={f.placeholder} minRows={1} />
            ))}
          </div>
        </div>
      </div>
    </LabSection>
  );
}

/* ============================ STAGE 06 · make it stick ============= */
function SuccessPasses({ data }) {
  return (
    <LabSection data={data}>
      <div style={{ borderTop: "1px solid var(--ink)" }}>
        {data.cards.map((c) => (
          <div key={c.id} style={{ display: "flex", gap: 18, padding: "22px 0",
            borderBottom: "1px solid var(--fog)" }}>
            <span style={{ color: "var(--signal)", fontFamily: "var(--font-mono)", fontSize: 15,
              flex: "0 0 auto", paddingTop: 2, lineHeight: 1.2 }}>—</span>
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ display: "flex", alignItems: "baseline", justifyContent: "space-between",
                gap: 12, marginBottom: 6 }}>
                <span style={{ fontFamily: "var(--font-sans)", fontWeight: 700, fontSize: 17,
                  letterSpacing: "-0.01em", color: "var(--ink)" }}>{c.key}</span>
                <LabTag kind={c.turn ? "turn" : "seed"} />
              </div>
              <div style={{ fontSize: 14.5, lineHeight: 1.45, color: "var(--ash)", marginBottom: 14 }}>{c.prompt}</div>
              <LabField id={"success." + c.id} kind={c.turn ? "turn" : "seed"} seed={c.seed}
                placeholder={c.placeholder} minRows={2} />
            </div>
          </div>
        ))}
      </div>
    </LabSection>
  );
}

/* ============================ STAGE 07 · assumption ranker ========= */
function AssumptionRanker({ data }) {
  const empties = Array.from({ length: data.emptyRows || 0 }, (_, i) => ({ id: "user" + (i + 1), turn: true }));
  const items = data.items.concat(empties);
  return (
    <LabSection data={data}>
      <RankHint />
      <Ranker labKey="assumptions.order" items={items} renderItem={(it) => (
        it.turn ? (
          <div style={{ display: "flex", alignItems: "flex-start", gap: 12 }}>
            <div style={{ flex: 1, minWidth: 0 }}>
              <LabField id={"assumptions.text." + it.id} kind="turn"
                placeholder={data.emptyPlaceholder} minRows={1} />
            </div>
            <div style={{ flex: "0 0 auto", paddingTop: 6 }}><LabTag kind="turn" /></div>
          </div>
        ) : (
          <RankDetail item={it} />
        )
      )} />
    </LabSection>
  );
}

/* ============================ STAGE 08 · opening + shock =========== */
function LineList({ audId, seedLines, placeholder }) {
  const { showSeeds } = uPCx(LabContext);
  const [stored, setStored] = useLab("openings." + audId + ".lines", null);
  const eff = stored === null ? (showSeeds ? seedLines.slice() : []) : stored;
  const rows = eff.length ? eff : [""];
  const commit = (arr) => setStored(arr);
  const setAt = (i, v) => { const a = rows.slice(); a[i] = v; commit(a); };
  const add = () => { if (rows.length < 7) commit(rows.concat("")); };
  const remove = (i) => { const a = rows.filter((_, j) => j !== i); commit(a.length ? a : [""]); };
  return (
    <div>
      <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
        {rows.map((line, i) => (
          <div key={i} style={{ display: "flex", alignItems: "flex-start", gap: 12,
            borderBottom: "1px solid var(--fog)", paddingBottom: 8 }}>
            <span style={{ fontFamily: "var(--font-mono)", fontSize: 12, color: "var(--signal)",
              flex: "0 0 auto", paddingTop: 10 }}>{String(i + 1).padStart(2, "0")}</span>
            <textarea value={line} rows={1} placeholder={placeholder} spellCheck={false}
              className="focus-ring lab-field" style={{ borderBottom: "0" }}
              onChange={(e) => setAt(i, e.target.value)}
              onInput={(e) => { e.target.style.height = "auto"; e.target.style.height = Math.max(e.target.scrollHeight, 22) + "px"; }} />
            <button onClick={() => remove(i)} className="focus-ring" aria-label="Remove line" style={{
              all: "unset", cursor: "pointer", flex: "0 0 auto", width: 26, height: 26, display: "inline-flex",
              alignItems: "center", justifyContent: "center", color: "var(--fg2)", marginTop: 4 }}>
              <Icon name="x" size={13} />
            </button>
          </div>
        ))}
      </div>
      <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", gap: 12, marginTop: 14 }}>
        <button onClick={add} disabled={rows.length >= 7} className="focus-ring" style={{
          all: "unset", cursor: rows.length >= 7 ? "default" : "pointer", display: "inline-flex",
          alignItems: "center", gap: 9, fontFamily: "var(--font-mono)", fontSize: 10.5, letterSpacing: "0.1em",
          textTransform: "uppercase", color: "var(--ink)", border: "1px solid var(--ink)", padding: "8px 13px",
          opacity: rows.length >= 7 ? 0.35 : 1 }}>
          <Icon name="plus" size={12} /> Add a line
        </button>
        <span style={{ fontFamily: "var(--font-mono)", fontSize: 10, letterSpacing: "0.12em",
          color: "var(--fg2)" }}>{rows.filter((l) => l.trim()).length} / 7</span>
      </div>
    </div>
  );
}

function OpeningQuestions({ data }) {
  const [aud, setAud] = uP(data.audiences[0].id);
  const audience = data.audiences.find((a) => a.id === aud) || data.audiences[0];
  return (
    <LabSection data={data}>
      {/* audience tabs */}
      <div style={{ display: "flex", gap: 0, border: "1px solid var(--ink)", marginBottom: 26 }}>
        {data.audiences.map((a, i) => {
          const on = a.id === aud;
          return (
            <button key={a.id} onClick={() => setAud(a.id)} className="focus-ring" style={{
              all: "unset", cursor: "pointer", flex: 1, textAlign: "center", padding: "13px 16px",
              borderRight: i < data.audiences.length - 1 ? "1px solid var(--ink)" : "none",
              background: on ? "var(--ink)" : "transparent", color: on ? "var(--paper)" : "var(--ink)",
              transition: "background var(--dur-fast) var(--ease)" }}>
              <div style={{ fontFamily: "var(--font-mono)", fontSize: 9.5, letterSpacing: "0.12em",
                textTransform: "uppercase", opacity: 0.65, marginBottom: 4 }}>Audience {a.id}</div>
              <div style={{ fontWeight: 700, fontSize: 15, letterSpacing: "-0.01em" }}>{a.label}</div>
            </button>
          );
        })}
      </div>

      {audience.hint && (
        <div style={{ display: "flex", alignItems: "baseline", gap: 10, marginBottom: 20, maxWidth: "62ch" }}>
          <LabTag kind="seed" />
          <span style={{ fontSize: 14.5, lineHeight: 1.5, color: "var(--ash)" }}>{audience.hint}</span>
        </div>
      )}

      {/* candidate lines */}
      <div style={{ display: "flex", alignItems: "center", gap: 10, marginBottom: 14 }}>
        <span style={{ fontFamily: "var(--font-mono)", fontSize: 10, letterSpacing: "0.14em",
          textTransform: "uppercase", color: "var(--fg2)" }}>Candidate opening lines</span>
        <span style={{ flex: 1, height: 1, background: "var(--fog)" }} />
        <LabTag kind="turn" />
      </div>
      <LineList key={aud} audId={aud} seedLines={audience.seedLines} placeholder={data.linePlaceholder} />

      {/* the shock */}
      <div style={{ marginTop: 34, borderTop: "1px solid var(--fog)", paddingTop: 26, maxWidth: 680 }}>
        <LabField key={aud + "-shock"} id={"openings." + aud + ".shock"}
          kind={audience.seedShock ? "seed" : "turn"} seed={audience.seedShock}
          label={data.shockLabel} placeholder={data.shockPlaceholder} minRows={2} />
      </div>
    </LabSection>
  );
}

Object.assign(window, {
  Grip, Ranker, VehicleFork, BeliefRanker, AudienceDoorways,
  SuccessPasses, AssumptionRanker, OpeningQuestions, LineList,
});
