/* Immersive case-study reader: full-screen modal + before/after reveal slider.
   Rendered over the board; opens when a clickable case card is clicked. */

const { useState: useStateCS, useRef: useRefCS, useEffect: useEffectCS, useCallback: useCallbackCS } = React;

/* ── Rich text: converts **bold** and *italic* in a string to nodes ── */
function renderRich(text) {
  if (!text) return null;
  const out = [];
  // Split on [label](url) links first, then **bold** / *italic* within plain runs.
  const linkParts = text.split(/(\[[^\]]+\]\([^)]+\))/g);
  linkParts.forEach((lp, li) => {
    const lm = /^\[([^\]]+)\]\(([^)]+)\)$/.exec(lp);
    if (lm) {
      out.push(
        <a key={`l${li}`} className="cs-link" href={lm[2]} target="_blank" rel="noopener noreferrer">{lm[1]}</a>
      );
      return;
    }
    const boldParts = lp.split(/(\*\*[^*]+\*\*)/g);
    boldParts.forEach((bp, bi) => {
      if (/^\*\*[^*]+\*\*$/.test(bp)) {
        out.push(<strong key={`l${li}b${bi}`}>{bp.slice(2, -2)}</strong>);
      } else {
        const italParts = bp.split(/(\*[^*]+\*)/g);
        italParts.forEach((ip, ii) => {
          if (/^\*[^*]+\*$/.test(ip)) {
            out.push(<em key={`l${li}b${bi}i${ii}`}>{ip.slice(1, -1)}</em>);
          } else if (ip) {
            out.push(ip);
          }
        });
      }
    });
  });
  return out;
}

/* ───────────────────── Before / After reveal slider ─────────────────────
   Two stacked images. `before` is the base layer (full). `after` sits on top,
   clipped to the RIGHT of the handle, so dragging the handle right reveals
   more of the `before` image underneath. Pointer + keyboard accessible. */
function BeforeAfterReveal({ before, after, beforeLabel, afterLabel, caption }) {
  const [pos, setPos] = useStateCS(52); // percent from left where the divider sits
  const wrapRef = useRefCS(null);
  const draggingRef = useRefCS(false);

  const setFromClientX = useCallbackCS((clientX) => {
    const el = wrapRef.current;
    if (!el) return;
    const rect = el.getBoundingClientRect();
    let p = ((clientX - rect.left) / rect.width) * 100;
    p = Math.max(0, Math.min(100, p));
    setPos(p);
  }, []);

  const onPointerDown = useCallbackCS((e) => {
    draggingRef.current = true;
    e.currentTarget.setPointerCapture?.(e.pointerId);
    setFromClientX(e.clientX);
  }, [setFromClientX]);

  const onPointerMove = useCallbackCS((e) => {
    if (!draggingRef.current) return;
    setFromClientX(e.clientX);
  }, [setFromClientX]);

  const onPointerUp = useCallbackCS(() => { draggingRef.current = false; }, []);

  const onKeyDown = useCallbackCS((e) => {
    if (e.key === "ArrowLeft") { setPos((p) => Math.max(0, p - 4)); e.preventDefault(); }
    else if (e.key === "ArrowRight") { setPos((p) => Math.min(100, p + 4)); e.preventDefault(); }
  }, []);

  return (
    <figure className="cs-figure cs-reveal-figure">
      <div
        className="cs-reveal"
        ref={wrapRef}
        onPointerDown={onPointerDown}
        onPointerMove={onPointerMove}
        onPointerUp={onPointerUp}
        onPointerCancel={onPointerUp}>
        {/* base = before */}
        <img className="cs-reveal__img" src={before} alt={beforeLabel} draggable="false" />
        {/* top = after, clipped to the right of the handle */}
        <div className="cs-reveal__top" style={{ clipPath: `inset(0 0 0 ${pos}%)` }}>
          <img className="cs-reveal__img" src={after} alt={afterLabel} draggable="false" />
        </div>

        <span className="cs-reveal__tag cs-reveal__tag--l" style={{ opacity: pos > 16 ? 1 : 0 }}>{beforeLabel}</span>
        <span className="cs-reveal__tag cs-reveal__tag--r" style={{ opacity: pos < 84 ? 1 : 0 }}>{afterLabel}</span>

        <div
          className="cs-reveal__handle"
          style={{ left: `${pos}%` }}
          role="slider"
          tabIndex={0}
          aria-label="Reveal before / after"
          aria-valuemin={0}
          aria-valuemax={100}
          aria-valuenow={Math.round(pos)}
          onKeyDown={onKeyDown}>
          <span className="cs-reveal__grip">
            <svg viewBox="0 0 24 24" width="20" height="20" aria-hidden="true">
              <path d="M10 7 L 5 12 L 10 17 M 14 7 L 19 12 L 14 17" stroke="currentColor" strokeWidth="2.2" fill="none" strokeLinecap="round" strokeLinejoin="round" />
            </svg>
          </span>
        </div>
      </div>
      {caption && <figcaption className="cs-caption">{caption}</figcaption>}
    </figure>
  );
}

/* ───────────────────── single artifact renderer ───────────────────── */
function CaseArt2({ art }) {
  if (art.type === "reveal") {
    return (
      <BeforeAfterReveal
        before={art.before}
        after={art.after}
        beforeLabel={art.beforeLabel}
        afterLabel={art.afterLabel}
        caption={art.caption} />
    );
  }
  if (art.type === "video") {
    return (
      <figure className="cs-figure">
        <video
          className="cs-media"
          src={art.src}
          autoPlay
          loop
          muted
          playsInline
          controls />
        {art.caption && <figcaption className="cs-caption">{art.caption}</figcaption>}
      </figure>
    );
  }
  if (art.type === "metrics") {
    return (
      <div className="cs-metrics">
        {art.cells.map((c, i) => (
          <div className="cs-metric" key={i}>
            <span className="cs-metric__big">{c.big}</span>
            <span className="cs-metric__label">{c.label}</span>
          </div>
        ))}
      </div>
    );
  }
  // default: image
  return (
    <figure className="cs-figure">
      <img className="cs-media" src={art.src} alt={art.caption || ""} draggable="false" loading="lazy" />
      {art.caption && <figcaption className="cs-caption">{art.caption}</figcaption>}
    </figure>
  );
}

/* ───────────────────── Case-study modal ───────────────────── */
function CaseStudyModal({ study, tocLabel, introLabel, closeLabel, onClose }) {
  const scrollRef = useRefCS(null);
  const [activeId, setActiveId] = useStateCS(null);
  const [progress, setProgress] = useStateCS(0);

  // ESC to close + scroll lock
  useEffectCS(() => {
    if (!study) return;
    const prev = document.body.style.overflow;
    document.body.style.overflow = "hidden";
    const onKey = (e) => { if (e.key === "Escape") onClose(); };
    window.addEventListener("keydown", onKey);
    // reset scroll to top on open
    requestAnimationFrame(() => { if (scrollRef.current) scrollRef.current.scrollTop = 0; });
    return () => {
      document.body.style.overflow = prev;
      window.removeEventListener("keydown", onKey);
    };
  }, [study, onClose]);

  // Scroll spy + progress bar
  useEffectCS(() => {
    if (!study) return;
    const root = scrollRef.current;
    if (!root) return;
    const onScroll = () => {
      const max = root.scrollHeight - root.clientHeight;
      setProgress(max > 0 ? Math.min(1, root.scrollTop / max) : 0);
      // active section = last whose top is above the 40% line
      const line = root.scrollTop + root.clientHeight * 0.4;
      let current = null;
      study.sections.forEach((s) => {
        const el = root.querySelector(`#sec-${s.id}`);
        if (el && el.offsetTop <= line) current = s.id;
      });
      setActiveId(current || (study.sections[0] && study.sections[0].id));
    };
    onScroll();
    root.addEventListener("scroll", onScroll, { passive: true });
    return () => root.removeEventListener("scroll", onScroll);
  }, [study]);

  if (!study) return null;

  const jumpTo = (id) => {
    const root = scrollRef.current;
    const el = root && root.querySelector(`#sec-${id}`);
    if (el && root) root.scrollTo({ top: el.offsetTop - 28, behavior: "smooth" });
  };

  return (
    <div className="cs-overlay" role="dialog" aria-modal="true" aria-label={study.title}>
      <div className="cs-scroll" ref={scrollRef}>
        <div className="cs-progress" style={{ transform: `scaleX(${progress})` }} aria-hidden="true"></div>
        <div className="cs-close-dock">
          <button type="button" className="cs-close" aria-label={closeLabel} onClick={onClose}>
            <svg viewBox="0 0 24 24" width="20" height="20" aria-hidden="true">
              <path d="M6 6 L 18 18 M 18 6 L 6 18" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" />
            </svg>
          </button>
        </div>
        <article className="cs-article">
          <div className="cs-layout">
            <nav className="cs-toc" aria-label={tocLabel}>
              <span className="cs-toc__label">{tocLabel}</span>
              <ul>
                {study.sections.map((s) => (
                  <li key={s.id}>
                    <button
                      type="button"
                      className={`cs-toc__link ${activeId === s.id ? "is-active" : ""}`}
                      onClick={() => jumpTo(s.id)}>
                      {s.eyebrow}
                    </button>
                  </li>
                ))}
              </ul>
            </nav>

            <div className="cs-main">
          {/* ── header ── */}
          <header className="cs-head">
            <div className="cs-tags">
              {study.tags.map((t) => <span className="cs-tag" key={t}>{t}</span>)}
            </div>
            <h1 className="cs-title">{study.title}</h1>
            <p className="cs-subtitle">{study.subtitle}</p>
            <div className="cs-meta">
              {study.meta.map((m) => (
                <div className="cs-meta__col" key={m.k}>
                  <span className="cs-meta__k">{m.k}</span>
                  <span className="cs-meta__v">{m.v}</span>
                </div>
              ))}
            </div>
          </header>

          {/* ── hero ── */}
          <figure className="cs-figure cs-hero-fig">
            <img className="cs-media" src={study.hero.src} alt={study.hero.caption} draggable="false" />
            {study.hero.caption && <figcaption className="cs-caption">{study.hero.caption}</figcaption>}
          </figure>

          <div className="cs-rule"></div>

          {/* ── sections ── */}
          <div className="cs-sections">
              {study.sections.map((s) => (
                <section className="cs-section" id={`sec-${s.id}`} key={s.id}>
                  <span className="cs-eyebrow">{s.eyebrow}</span>
                  <h2 className="cs-headline">{s.headline}</h2>
                  {s.body && <p className="cs-body">{renderRich(s.body)}</p>}

                  {s.list && (
                    <div className="cs-rolelist">
                      <span className="cs-rolelist__label">{s.list.label}</span>
                      <ul>
                        {s.list.items.map((it, i) => <li key={i}>{renderRich(it)}</li>)}
                      </ul>
                    </div>
                  )}

                  {s.arts && s.arts.map((art, i) => <CaseArt2 art={art} key={i} />)}

                  {s.quote && (
                    <blockquote className="cs-quote">
                      <p>{s.quote.text}</p>
                      <cite>— {s.quote.name}<span>{s.quote.role}</span></cite>
                    </blockquote>
                  )}

                  {s.reflection && (
                    <ul className="cs-reflection">
                      {s.reflection.map((r, i) => (
                        <li key={i}><strong>{r.lead}</strong>— {r.body}</li>
                      ))}
                    </ul>
                  )}
                </section>
              ))}
          </div>

          <div className="cs-foot">
            <button type="button" className="cs-foot__close" onClick={onClose}>
              {closeLabel}
            </button>
          </div>
            </div>
          </div>
        </article>
      </div>
    </div>
  );
}

Object.assign(window, { BeforeAfterReveal, CaseStudyModal, renderRich });
