/* global React */
const { useState, useEffect, useRef } = React;

/* ============================================================
   Motion hooks
   --------------------------------------------------------
   useReveal : adds `is-in` class when the element scrolls
               into view (once). Pair with `.cs-reveal` CSS.
   useCountUp: animates a numeric string from 0 to target
               with 800ms breath easing. Non-numeric targets
               (e.g. "11/12") return untouched.
   ============================================================ */
function useReveal(threshold = 0.15) {
  const ref = useRef(null);
  const [seen, setSeen] = useState(false);
  useEffect(() => {
    const el = ref.current;
    if (!el || seen) return;

    // Already in viewport on mount → reveal immediately (animation still plays).
    const rect = el.getBoundingClientRect();
    const vh = window.innerHeight || document.documentElement.clientHeight;
    if (rect.top < vh && rect.bottom > 0) { setSeen(true); return; }

    // No IO at all → reveal immediately.
    if (typeof IntersectionObserver === "undefined") { setSeen(true); return; }

    let obs;
    try {
      obs = new IntersectionObserver(
        (entries) => entries.forEach(e => {
          if (e.isIntersecting) { setSeen(true); obs.disconnect(); clearTimeout(timer); }
        }),
        { threshold }
      );
      obs.observe(el);
    } catch (err) {
      setSeen(true);
      return;
    }

    // Safety net — IO is unreliable in some iframe contexts. Reveal after 600ms
    // regardless. The animation still plays; this prevents stuck-invisible elements.
    const timer = setTimeout(() => { setSeen(true); obs && obs.disconnect(); }, 600);

    return () => { obs && obs.disconnect(); clearTimeout(timer); };
  }, [seen, threshold]);
  return [ref, seen ? "cs-reveal is-in" : "cs-reveal"];
}

function useCountUp(target, opts = {}) {
  const { duration = 800, trigger = true } = opts;
  const raw = String(target);
  const numeric = parseFloat(raw.replace(/,/g, ""));
  const decimals = (raw.split(".")[1] || "").length;
  const valid = !Number.isNaN(numeric) && /^-?[0-9.,]+$/.test(raw);
  const [val, setVal] = useState(valid ? 0 : numeric);
  useEffect(() => {
    if (!valid || !trigger) return;
    let raf, start;
    const ease = (t) => 1 - Math.pow(1 - t, 3); // ease-out cubic, breath-like
    const step = (ts) => {
      if (!start) start = ts;
      const t = Math.min(1, (ts - start) / duration);
      setVal(numeric * ease(t));
      if (t < 1) raf = requestAnimationFrame(step);
    };
    raf = requestAnimationFrame(step);
    return () => raf && cancelAnimationFrame(raf);
  }, [valid, trigger, numeric, duration]);
  if (!valid) return raw;
  return val.toLocaleString(undefined, { minimumFractionDigits: decimals, maximumFractionDigits: decimals });
}

/* ============================================================
   CS-01 · Engagement card  —  case-study masthead
   ============================================================ */
function CSEngagement({ id, sector, geography, title, kpis }) {
  const [ref, cls] = useReveal();
  return (
    <div className={`cs-engagement ${cls}`} ref={ref}>
      <div className="cs-engagement-bar">
        <span className="cse-id"><span className="cse-mark"></span>{id}</span>
        <span>{sector} · {geography}</span>
      </div>
      <div className="cs-engagement-body">
        <h3 className="cs-engagement-title">{title}</h3>
        <div className="cs-engagement-sub">Engagement record · ratified for publication</div>
        <div className="cs-engagement-kpis">
          {kpis.map((k, i) => (
            <div className={`cs-engagement-kpi ${k.featured ? "featured" : ""}`} key={i}>
              <div className="k-label">{k.label}</div>
              <div className="k-value">
                {k.value}
                {k.unit && <span className="k-unit">{k.unit}</span>}
              </div>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

/* ============================================================
   CS-02 · Phase ribbon
   ============================================================ */
function CSPhases({ phases }) {
  return (
    <div className="cs-phases">
      {phases.map((p, i) => (
        <div className="cs-phase" data-state={p.state} key={i}>
          <div className="cp-head">
            <span className="cp-tick"></span>
            <span>Phase {String(i + 1).padStart(2, "0")}</span>
          </div>
          <h4 className="cp-name">{p.name}</h4>
          <div className="cp-meta">{p.meta}</div>
          <p className="cp-desc">{p.desc}</p>
        </div>
      ))}
    </div>
  );
}

/* ============================================================
   CS-03 · Week ledger
   ============================================================ */
function CSLedger({ rows }) {
  return (
    <div className="cs-ledger">
      {rows.map((r, i) => (
        <div className="cs-ledger-row" data-kind={r.kind} key={i}>
          <div className="lr-week">
            {r.week}
            <span className="lr-date">{r.date}</span>
          </div>
          <div className="lr-pip"></div>
          <div className="lr-body">
            <div className="lr-title">{r.title}</div>
            {r.note && <div className="lr-note">{r.note}</div>}
          </div>
          <div className="lr-kind">{r.kindLabel}</div>
        </div>
      ))}
    </div>
  );
}

/* ============================================================
   CS-04 · Milestone marker
   ============================================================ */
function CSMilestone({ date, week, kind, title, desc }) {
  const [ref, cls] = useReveal();
  return (
    <div className={`cs-milestone ${cls}`} ref={ref}>
      <div className="ms-date">
        {date}
        <span className="ms-week">{week}</span>
      </div>
      <div className="ms-body">
        <div className="ms-kind">{kind}</div>
        <h3 className="ms-title">{title}</h3>
        <p className="ms-desc">{desc}</p>
      </div>
    </div>
  );
}

/* ============================================================
   CS-05 · Tuesday split  —  before/after of a workday
   ============================================================ */
function CSTuesday({ before, after }) {
  const renderCol = (col, kind) => (
    <div className={`cs-tuesday-col ${kind}`}>
      <div className="ct-label">
        <span>{col.label}</span>
        <span className="ct-state">{col.state}</span>
      </div>
      <h5 className="ct-title">{col.title}</h5>
      <div className="cs-tuesday-grid">
        {col.slots.map((s, i) => (
          <React.Fragment key={i}>
            <div className="cs-tuesday-hour">{s.hour}</div>
            <div className="cs-tuesday-slot" data-kind={s.kind}>
              <span>{s.label}</span>
              {s.tag && <span className="slot-tag">{s.tag}</span>}
            </div>
          </React.Fragment>
        ))}
      </div>
      <div className="cs-tuesday-foot">
        <span>{col.footLabel}</span>
        <strong>{col.footValue}</strong>
      </div>
    </div>
  );
  return (
    <div className="cs-tuesday">
      {renderCol(before, "before")}
      {renderCol(after, "after")}
    </div>
  );
}

/* ============================================================
   CS-06 · Hours-found ledger
   ============================================================ */
function CSHours({ rows, total }) {
  return (
    <div className="cs-hours">
      <div className="cs-hours-head">
        <span>Task · what was eating the week</span>
        <span>Source · where the time came from</span>
        <span style={{textAlign:"right"}}>Hours</span>
      </div>
      {rows.map((r, i) => (
        <div className="cs-hours-row" key={i}>
          <div className="h-task">
            {r.task}
            <span className="h-task-sub">{r.subtitle}</span>
          </div>
          <div className="h-source">{r.source}</div>
          <div className="h-num">
            {r.hours}
            <span className="h-num-unit">h/wk</span>
          </div>
        </div>
      ))}
      <div className="cs-hours-total">
        <span className="ht-label">{total.label}</span>
        <span className="ht-source">{total.source}</span>
        <span className="ht-num">
          {total.hours}
          <span className="ht-num-unit">h/wk</span>
        </span>
      </div>
    </div>
  );
}

/* ============================================================
   CS-07 · Workflow diff
   ============================================================ */
function CSWfdiff({ name, was, now }) {
  return (
    <div className="cs-wfdiff">
      <div className="cs-wfdiff-bar">
        <span>Workflow · {name}</span>
        <span>Replaced {now.replacedOn}</span>
      </div>
      <div className="cs-wfdiff-grid">
        <div className="cs-wfdiff-col was">
          <div className="wd-state">Was · {was.duration}</div>
          <h5 className="wd-h">{was.title}</h5>
          <ol className="cs-wfdiff-steps">
            {was.steps.map((s, i) => (
              <li key={i} data-cut={s.cut ? "true" : "false"}>
                <span className="s-n">{String(i + 1).padStart(2, "0")}</span>
                <span>{s.label}</span>
                <span className="s-who">{s.who}</span>
              </li>
            ))}
          </ol>
        </div>
        <div className="cs-wfdiff-col now">
          <div className="wd-state">Now · {now.duration}</div>
          <h5 className="wd-h">{now.title}</h5>
          <ol className="cs-wfdiff-steps">
            {now.steps.map((s, i) => (
              <li key={i}>
                <span className="s-n">{String(i + 1).padStart(2, "0")}</span>
                <span>{s.label}</span>
                <span className="s-who" data-actor={s.actor}>{s.who}</span>
              </li>
            ))}
          </ol>
        </div>
      </div>
    </div>
  );
}

/* ============================================================
   CS-08 · Agent roster
   ============================================================ */
function CSRoster({ agents }) {
  return (
    <div className="cs-roster">
      {agents.map((a, i) => (
        <div className="cs-agent" key={i}>
          <div className="ca-bar">
            <span>{a.id}</span>
            <span className="ca-status">{a.status}</span>
          </div>
          <h4 className="ca-name">{a.name}</h4>
          <div className="ca-role">{a.role}</div>
          <p className="ca-holds">{a.holds}</p>
          <div className="ca-rule"></div>
          <div className="ca-meta">
            <span>Ratified <strong>{a.ratified}</strong></span>
            <span>Cadence <strong>{a.cadence}</strong></span>
          </div>
        </div>
      ))}
    </div>
  );
}

/* ============================================================
   CS-09 · Scope card
   ============================================================ */
function CSScope({ agent, tag, granted, denied, refused }) {
  return (
    <div className="cs-scope">
      <div className="cs-scope-head">
        <div className="cs-scope-name">{agent}</div>
        <div className="cs-scope-tag">{tag}</div>
      </div>
      <div className="cs-scope-body">
        <div className="cs-scope-col granted">
          <h5><span className="pip"></span>Granted</h5>
          <ul>{granted.map((g, i) => <li key={i}>{g}</li>)}</ul>
        </div>
        <div className="cs-scope-col denied">
          <h5><span className="pip"></span>Denied</h5>
          <ul>{denied.map((d, i) => <li key={i}>{d}</li>)}</ul>
        </div>
        <div className="cs-scope-col refused">
          <h5><span className="pip"></span>Refusals</h5>
          <ul>
            {refused.map((r, i) => (
              <li key={i}><span className="r-key">{r.key}</span>{r.text}</li>
            ))}
          </ul>
        </div>
      </div>
    </div>
  );
}

/* ============================================================
   CS-10 · Gate log
   ============================================================ */
function CSGatelog({ rows }) {
  return (
    <div className="cs-gatelog">
      {rows.map((r, i) => (
        <div className="cs-gatelog-row" data-status={r.status} key={i}>
          <div className="g-key">{r.key}</div>
          <div className="g-body">
            <div className="g-name">{r.name}</div>
            {r.detail && <div className="g-detail">{r.detail}</div>}
          </div>
          <div className="g-actor">{r.actor}</div>
          <div className="g-status">
            <span className="mark"></span>
            {r.status === "pass" ? "Pass" : "Returned"}
          </div>
        </div>
      ))}
    </div>
  );
}

Object.assign(window, {
  CSEngagement, CSPhases, CSLedger, CSMilestone,
  CSTuesday, CSHours, CSWfdiff,
  CSRoster, CSScope, CSGatelog
});
