// Method 8 — demo · Formative workshop with live polling.
// Facilitator opens a poll → 18 votes stream in → bars animate → AI synthesis
// → running maturity profile accumulates. The live, in-the-room moment.

const { Ico, I, PageHead, useNav } = window;

const JOINED = 18;

const POLLS = [
  { t: 'Critical controls defined', q: 'Our critical controls are clearly defined for every material risk.',
    target: [0, 1, 3, 8, 6], status: 'done',
    syn: 'Strong agreement — controls are well defined on paper. This is the workshop\'s high-water mark; the gap is in what happens next.' },
  { t: 'Frontline empowerment', q: 'Frontline workers feel able to stop a job when a critical control is missing.',
    target: [1, 2, 5, 7, 3], status: 'done',
    syn: 'Mostly positive, but a meaningful minority disagree. Stop-work authority exists but isn\'t felt evenly across crews and contractors.' },
  { t: 'Field verification', q: 'Critical controls are verified in the field — not just signed off on paper.',
    target: [3, 6, 5, 3, 1], status: 'active',
    syn: 'Lowest of the session at 2.6/5. Half the room sits at \u201cdisagree\u201d or below — verification is documented but not consistently done at the face. Recommend a formative action on field-leader verification routines before the next gap assessment.' },
  { t: 'Learning from incidents', q: 'We learn from incidents and near-misses, and visibly act on them.',
    target: [1, 3, 6, 6, 2], status: 'upcoming', syn: 'Middling. Reporting happens; closing the loop back to crews is inconsistent.' },
  { t: 'Visible leadership', q: 'Leaders are visible and consistent on critical-risk discipline.',
    target: [0, 2, 4, 8, 4], status: 'upcoming', syn: 'Solid. Leadership presence is felt, especially on day shift.' },
];

const SCALE = ['Strongly disagree', 'Disagree', 'Neutral', 'Agree', 'Strongly agree'];
const SCOLORS = ['#f04438', '#f79009', '#fdb022', '#66c61c', '#17b26a'];

function avgOf(counts) {
  const total = counts.reduce((a, b) => a + b, 0);
  if (!total) return 0;
  return counts.reduce((s, c, i) => s + c * (i + 1), 0) / total;
}
function shuffle(a) { const r = a.slice(); for (let i = r.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [r[i], r[j]] = [r[j], r[i]]; } return r; }
function scoreColor(v) { return v >= 4 ? '#17b26a' : v >= 3 ? '#66c61c' : v >= 2.5 ? '#fdb022' : v >= 2 ? '#f79009' : '#f04438'; }

function WorkshopView() {
  const { go } = useNav();
  const [idx, setIdx] = React.useState(2);              // start on the active "field verification" poll
  const [phase, setPhase] = React.useState('idle');      // idle | open | closed
  const [votes, setVotes] = React.useState([0, 0, 0, 0, 0]);
  // profile: completed polls 0,1 seeded
  const [profile, setProfile] = React.useState({ 0: avgOf(POLLS[0].target), 1: avgOf(POLLS[1].target) });
  const seqRef = React.useRef([]);
  const timerRef = React.useRef(null);

  const poll = POLLS[idx];
  const total = votes.reduce((a, b) => a + b, 0);
  const liveAvg = avgOf(votes);

  // measured track width — percentage/flex sizing can't resolve inside a 1fr
  // grid track, so the bar is sized in absolute pixels from the live measurement
  const trackRef = React.useRef(null);
  const [tw, setTw] = React.useState(0);
  React.useLayoutEffect(() => {
    const el = trackRef.current; if (!el) return;
    const ro = new ResizeObserver(() => setTw(el.clientWidth));
    ro.observe(el); setTw(el.clientWidth);
    return () => ro.disconnect();
  }, [phase]);

  React.useEffect(() => () => clearInterval(timerRef.current), []);

  const openPoll = () => {
    setVotes([0, 0, 0, 0, 0]);
    setPhase('open');
    const seq = shuffle(poll.target.flatMap((c, i) => Array(c).fill(i)));
    seqRef.current = seq;
    let k = 0;
    clearInterval(timerRef.current);
    timerRef.current = setInterval(() => {
      const b = seqRef.current[k];
      setVotes(v => { const nv = v.slice(); nv[b] += 1; return nv; });
      k++;
      if (k >= seqRef.current.length) { clearInterval(timerRef.current); setTimeout(() => setPhase('closed'), 250); }
    }, 95);
  };
  const closeNow = () => { clearInterval(timerRef.current); setVotes(poll.target); setPhase('closed'); };
  const nextPoll = () => {
    setProfile(p => ({ ...p, [idx]: avgOf(votes.some(Boolean) ? votes : poll.target) }));
    const ni = idx + 1;
    if (ni < POLLS.length) { setIdx(ni); setPhase('idle'); setVotes([0, 0, 0, 0, 0]); }
    else { setPhase('done'); }
  };

  const shownAvg = phase === 'idle' ? 0 : liveAvg;
  const sessionDims = Object.keys(profile).length;
  const sessionAvg = sessionDims ? (Object.values(profile).reduce((a, b) => a + b, 0) / sessionDims) : 0;

  return (
    <>
      <PageHead
        eyebrow={<><span>Formative workshop</span><span className="dot"/><span>Effectiveness scan · maturity</span><span className="dot"/><span>Facilitated by Method 8</span></>}
        title="Critical Risk Management — maturity workshop"
        sub={<>St Ives leadership team, live. The room rates each statement 1–5; Method 8 polls in real time and synthesises the result so the conversation moves to <b>why</b>, not <b>what</b>.</>}
        actions={<>
          <span className="wk-join"><Ico d={I.users} sw={2}/> <b>{JOINED}</b> joined</span>
          <button className="btn btn-sec"><Ico d={I.ext} sw={2}/> Export profile</button>
        </>}/>

      <div className="grid-2">
        <div>
          <div className="wk-stage">
            <div className="wk-head">
              <span className="wk-live">Live</span>
              <div style={{ font: '600 13px/17px Inter', color: 'var(--ink3)' }}>Poll {idx + 1} of {POLLS.length}</div>
              <div className="wk-join" style={{ marginLeft: 'auto' }}>
                <span className="resp-live"><span className="pulse-dot"/> <b>{total}</b>/{JOINED} responded</span>
              </div>
            </div>
            <div className="wk-body">
              {phase === 'done' ? (
                <div style={{ textAlign: 'center', padding: '30px 10px' }}>
                  <div className="feed-ic ok" style={{ width: 52, height: 52, margin: '0 auto 14px' }}><Ico d={I.check} sw={2.4} size={26}/></div>
                  <div style={{ font: '600 24px/30px Inter', letterSpacing: '-0.02em' }}>Workshop complete</div>
                  <div style={{ font: '400 14px/21px Inter', color: 'var(--ink4)', maxWidth: 560, margin: '8px auto 0' }}>5 dimensions scored across {JOINED} participants. Method 8 has drafted a formative action plan — field verification is the priority.</div>
                  <button className="btn btn-ai" style={{ margin: '18px auto 0' }} onClick={() => go('report')}><Ico d={I.spark} sw={2}/> Review the formative action plan</button>
                </div>
              ) : (
                <>
                  <div className="wk-qn">Dimension · {poll.t}</div>
                  <div className="wk-q">{poll.q}</div>

                  <div className="wk-scale-cap"><span>1 · Strongly disagree</span><span>5 · Strongly agree</span></div>
                  <div className="wk-bars">
                    {SCALE.map((lab, i) => {
                      const c = votes[i];
                      const w = total ? (c / total) * tw : 0;
                      return (
                        <div key={i} className="wk-bar">
                          <div className="bl">{i + 1} · {lab.split(' ')[0]} <small>{lab}</small></div>
                          <div className="wk-track" ref={i === 0 ? trackRef : null}><div className="wk-seg" style={{ width: w, background: SCOLORS[i] }}/></div>
                          <div className="bv">{c}</div>
                        </div>
                      );
                    })}
                  </div>

                  <div className="wk-ctrl">
                    {phase === 'idle' && <button className="btn-launch go" onClick={openPoll}><Ico d={I.poll} sw={2.2} style={{ color: '#fff' }}/> Open poll to the room</button>}
                    {phase === 'open' && <><button className="btn-launch stop" onClick={closeNow}>Close &amp; reveal</button><span className="wk-tally">Collecting — <b>{total}</b> of {JOINED} in…</span></>}
                    {phase === 'closed' && <button className="btn-launch stop" onClick={nextPoll}>{idx + 1 < POLLS.length ? 'Next poll →' : 'Finish workshop'}</button>}
                    {phase !== 'idle' && (
                      <div className="wk-avg">
                        <div><div className="av-l">Room average</div></div>
                        <div className="av-n" style={{ color: scoreColor(shownAvg) }}>{shownAvg.toFixed(1)}<span style={{ font: '500 16px/1 Inter', color: 'var(--ink4)' }}>/5</span></div>
                      </div>
                    )}
                  </div>

                  {phase === 'closed' && (
                    <div className="aisum" style={{ marginTop: 18, marginBottom: 0 }}>
                      <div className="aisum-ic"><Ico d={I.spark} sw={2.2} size={16} style={{ color: '#fff' }}/></div>
                      <div className="aisum-body"><span className="aisum-text">{poll.syn}</span></div>
                      <span className="aisum-tag">AI synthesis</span>
                    </div>
                  )}
                </>
              )}
            </div>
          </div>
        </div>

        <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
          <div className="card">
            <div className="card-head"><div className="card-head-l"><h2>Session agenda</h2><div className="sub">5 maturity dimensions</div></div></div>
            <div className="card-body" style={{ padding: 8 }}>
              <div className="wk-agenda">
                {POLLS.map((p, i) => {
                  const done = profile[i] != null && i !== idx;
                  const on = i === idx;
                  return (
                    <div key={i} className={`wk-ag-item ${on ? 'on' : ''} ${done ? 'done' : ''}`} onClick={() => { if (i !== idx && phase !== 'open') { setIdx(i); setPhase(profile[i] != null ? 'closed' : 'idle'); setVotes(profile[i] != null ? p.target : [0,0,0,0,0]); } }}>
                      <span className="agn">{done ? <Ico d={I.check} sw={3} size={12}/> : i + 1}</span>
                      <span className="agt">{p.t}</span>
                      {profile[i] != null && <span className="agv" style={{ color: scoreColor(profile[i]) }}>{profile[i].toFixed(1)}</span>}
                    </div>
                  );
                })}
              </div>
            </div>
          </div>

          <div className="card">
            <div className="card-head"><div className="card-head-l"><h2>Maturity profile</h2><div className="sub">Builds as the room votes</div></div>
              <div className="card-head-r"><span className="badge violet">{sessionAvg ? sessionAvg.toFixed(1) : '–'}/5 avg</span></div>
            </div>
            <div className="card-body" style={{ paddingTop: 10 }}>
              {POLLS.map((p, i) => {
                const v = (i === idx && phase !== 'idle') ? liveAvg : profile[i];
                return (
                  <div key={i} className="prof-row">
                    <span className="pn">{p.t}</span>
                    <span className="prof-meter"><i style={{ width: `${(v || 0) / 5 * 100}%`, background: scoreColor(v || 0) }}/></span>
                    <span className="pv" style={{ color: v ? scoreColor(v) : 'var(--ink4)' }}>{v ? v.toFixed(1) : '–'}</span>
                  </div>
                );
              })}
              <div style={{ marginTop: 12, font: '400 12px/17px Inter', color: 'var(--ink4)' }}>
                Formative, not graded — the score starts the conversation. Results feed straight into the gap assessment and the improvement plan.
              </div>
            </div>
          </div>
        </div>
      </div>
    </>
  );
}

Object.assign(window, { WorkshopView });
