/* ══ OM Group ERP — Analysis Studio · Correlation Explorer & Briefing ═════
   Correlation: every metric with real variance in the live series is paired
   with every other, Pearson-scored, with an interactive scatter and fitted
   regression. Briefing: the same numbers written as an analyst would.    */
const { useState: exSt, useMemo: exMemo, useRef: exRef } = React;

function exRcol(r) {
  const a = Math.abs(r);
  if (a < 0.2) return { bg: '#F7F6F4', fg: '#A8A4A0' };
  const base = r > 0 ? [22, 163, 74] : [220, 38, 38];
  const alpha = 0.1 + a * 0.62;
  return { bg: 'rgba(' + base.join(',') + ',' + alpha.toFixed(2) + ')', fg: a > 0.55 ? '#fff' : '#1A1917' };
}

function StScatter({ pair, grain, labels }) {
  const [w, wrap] = window.IC.useWidth(560);
  const H = 300, padL = 56, padR = 18, padT = 18, padB = 34;
  const iw = Math.max(40, w - padL - padR), ih = Math.max(40, H - padT - padB);
  const xs = pair.x.values, ys = pair.y.values;
  const xMin = Math.min.apply(null, xs), xMax = Math.max.apply(null, xs);
  const yMin = Math.min.apply(null, ys), yMax = Math.max.apply(null, ys);
  const xSpan = (xMax - xMin) || 1, ySpan = (yMax - yMin) || 1;
  const X = v => padL + ((v - xMin) / xSpan) * iw;
  const Y = v => padT + ih - ((v - yMin) / ySpan) * ih;
  const fitA = pair.intercept + pair.slope * xMin, fitB = pair.intercept + pair.slope * xMax;
  const col = pair.r >= 0 ? '#16A34A' : '#DC2626';
  return (
    <div ref={wrap} className="ic-chart">
      <svg className="st-scatter" width="100%" height={H} viewBox={'0 0 ' + w + ' ' + H}>
        {[0, 0.25, 0.5, 0.75, 1].map((f, i) => (
          <g key={i}>
            <line x1={padL} x2={padL + iw} y1={padT + ih - f * ih} y2={padT + ih - f * ih} stroke={i === 0 ? '#E5E3E0' : '#F1EFEC'} />
            <text x={padL - 8} y={padT + ih - f * ih + 3.5} textAnchor="end" fontSize="9" fill="#A8A4A0" fontWeight="500">{window.IC.short(yMin + ySpan * f)}</text>
          </g>
        ))}
        {[0, 0.5, 1].map((f, i) => (
          <text key={'x' + i} x={padL + f * iw} y={H - 16} textAnchor={i === 0 ? 'start' : i === 2 ? 'end' : 'middle'} fontSize="9" fill="#A8A4A0" fontWeight="500">{window.IC.short(xMin + xSpan * f)}</text>
        ))}
        <line x1={X(xMin)} y1={Y(fitA)} x2={X(xMax)} y2={Y(fitB)} stroke={col} strokeWidth="2" strokeDasharray="6 4" opacity=".75" />
        {xs.map((x, i) => (
          <circle key={i} cx={X(x)} cy={Y(ys[i])} r="5" fill={col} fillOpacity=".2" stroke={col} strokeWidth="1.8"
            onMouseMove={e => window.ICTooltip.show(e, {
              title: labels[i] || (grain + ' ' + (i + 1)),
              rows: [{ dot: col, k: pair.x.label, v: window.IC.fmt(x, pair.x.fmt) }, { dot: col, k: pair.y.label, v: window.IC.fmt(ys[i], pair.y.fmt) }],
            })}
            onMouseLeave={() => window.ICTooltip.hide()}
            style={{ cursor: 'pointer', transition: 'r .18s cubic-bezier(.16,1,.3,1)' }} />
        ))}
        <text x={padL + iw} y={padT + 12} textAnchor="end" fontSize="10.5" fontWeight="800" fill={col}>r = {pair.r.toFixed(3)} · R² = {pair.r2.toFixed(2)}</text>
        <text x={padL + iw / 2} y={H - 3} textAnchor="middle" fontSize="9.5" fill="#6B7068" fontWeight="700">{pair.x.label} →</text>
      </svg>
    </div>
  );
}

function StudioCorrelation({ ctx }) {
  const DEng = window.DecisionEngine;
  const corr = exMemo(() => DEng.correlations(ctx), [ctx]);
  const [sel, setSel] = exSt(0);
  const labels = ctx.ser.points.map(p => p.label);

  if (corr.n < 3 || !corr.pairs.length) return (
    <StEmpty title="Not enough points to correlate"
      msg="Correlation needs at least three buckets with variance. Widen the period or pick a finer grain — the matrix rebuilds itself from whatever the data supports." />
  );

  const pair = corr.pairs[Math.min(sel, corr.pairs.length - 1)];
  const strong = corr.pairs.filter(p => Math.abs(p.r) >= 0.6);

  return (
    <div>
      <p className="st-lede">
        Every metric with real variance across the <b>{corr.n} {corr.grain} buckets</b> in scope, paired with every other —
        {' '}{corr.pairs.length} relationships, {strong.length} of them strong. Correlation is not causation; it is where to look.
      </p>

      <div className="st-2colr">
        <div className="i-card">
          <div className="i-card-hd">
            <div><div className="i-card-t">{pair.x.label} vs {pair.y.label}</div>
              <div className="i-card-s">{pair.strength} {pair.r >= 0 ? 'positive' : 'negative'} relationship · fitted least-squares line · {pair.n} points</div></div>
          </div>
          <StScatter pair={pair} grain={corr.grain} labels={labels} />
          <div style={{ marginTop: 12, paddingTop: 11, borderTop: '1px dashed var(--iLine)', fontSize: 11, color: 'var(--iInk2)', lineHeight: 1.6 }}>
            Across {pair.n} {corr.grain} buckets, a one-unit rise in <b style={{ color: 'var(--iInk)' }}>{pair.x.label}</b> moves{' '}
            <b style={{ color: 'var(--iInk)' }}>{pair.y.label}</b> by {window.IC.fmt(pair.slope, pair.y.fmt)} on the fitted line, and the relationship
            explains {(pair.r2 * 100).toFixed(0)}% of the variation. {Math.abs(pair.r) < 0.4
              ? 'That is weak — treat it as coincidence until a longer window says otherwise.'
              : Math.abs(pair.r) < 0.7 ? 'That is a real but partial relationship — other factors are doing the rest of the work.'
                : 'That is tight enough to plan around, and tight enough that breaking the link should be investigated.'}
          </div>
        </div>

        <div className="i-card" style={{ padding: '14px 12px' }}>
          <div className="i-card-hd" style={{ padding: '0 4px' }}><div><div className="i-card-t">Strongest relationships</div><div className="i-card-s">Ranked by absolute correlation</div></div></div>
          <div style={{ maxHeight: 'min(52vh,460px)', overflowY: 'auto' }}>
            {corr.pairs.slice(0, 40).map((p, i) => (
              <div key={i} className={'st-pair' + (i === sel ? ' on' : '')} onClick={() => setSel(i)}>
                <span className="st-pair-l">{p.x.label} <em>vs</em> {p.y.label}</span>
                <span className="st-pair-r" style={{ color: Math.abs(p.r) < 0.2 ? 'var(--iInk3)' : p.r > 0 ? '#15803D' : '#B91C1C' }}>{p.r >= 0 ? '+' : ''}{p.r.toFixed(2)}</span>
              </div>
            ))}
          </div>
        </div>
      </div>

      <StSec title="Correlation matrix" sub="Green means the pair moves together, red means they move against each other. Click any cell to open it as a scatter.">
        <div className="st-mx-wrap">
          <table className="st-mx">
            <thead>
              <tr><th className="rh">Metric</th>{corr.metrics.map(m => <th key={m.key} title={m.label}>{m.label.length > 10 ? m.label.slice(0, 9) + '…' : m.label}</th>)}</tr>
            </thead>
            <tbody>
              {corr.metrics.map(a => (
                <tr key={a.key}>
                  <td className="rh">{a.label}</td>
                  {corr.metrics.map(b => {
                    if (a.key === b.key) return <td key={b.key}><div className="st-mx-c" style={{ background: '#F1EFEC', color: '#C8C4BF' }}>1.0</div></td>;
                    const p = corr.pairs.find(z => (z.x.key === a.key && z.y.key === b.key) || (z.x.key === b.key && z.y.key === a.key));
                    if (!p) return <td key={b.key}></td>;
                    const c = exRcol(p.r);
                    return <td key={b.key}>
                      <div className="st-mx-c" style={{ background: c.bg, color: c.fg }}
                        onClick={() => setSel(corr.pairs.indexOf(p))}
                        onMouseMove={e => window.ICTooltip.show(e, { title: p.x.label + ' vs ' + p.y.label, rows: [{ k: 'Correlation', v: p.r.toFixed(3) }, { k: 'Strength', v: p.strength }, { k: 'Points', v: String(p.n) }], foot: 'Click to open the scatter' })}
                        onMouseLeave={() => window.ICTooltip.hide()}>
                        {p.r.toFixed(2).replace('0.', '.')}
                      </div>
                    </td>;
                  })}
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </StSec>
    </div>
  );
}

/* ══ EXECUTIVE BRIEFING ═══════════════════════════════════════════════════ */
function StudioBriefing({ ctx }) {
  const DEng = window.DecisionEngine;
  const bundle = exMemo(() => {
    const dv = DEng.drivers(ctx);
    const rk = DEng.risks(ctx);
    const op = DEng.opportunities(ctx);
    const season = ctx.ser.grain === 'month' ? 12 : ctx.ser.grain === 'cycle' ? 24 : ctx.ser.grain === 'quarter' ? 4 : 0;
    const fc = DEng.forecastModels(ctx.ser.points, 3, { valueKey: ctx.mode === 'purchase' ? 'purchaseValue' : 'revenue', season });
    return { dv, rk, op, fc, story: DEng.story(ctx, dv, rk, op, fc) };
  }, [ctx]);

  function copyBrief() {
    const txt = 'OM GROUP — EXECUTIVE BRIEFING\n' + ctx.period.label + (ctx.cmpPeriod ? ' vs ' + ctx.cmpPeriod.label : '') + '\n\n' +
      bundle.story.map(s => s.h.toUpperCase() + '\n' + s.body).join('\n\n');
    if (navigator.clipboard) navigator.clipboard.writeText(txt).then(() => window.toast && window.toast('Briefing copied', 'ok'));
  }

  return (
    <div>
      <p className="st-lede">
        Written from the same live derivation everything else on this page uses — <b>{ctx.ds.sales.length + ctx.ds.purchases.length + ctx.ds.diesel.length + ctx.ds.transport.length} records</b> in scope.
        Re-read it after any ERP change and the sentences will have moved with the numbers.
      </p>

      <div className="i-card" style={{ padding: '6px 24px 20px' }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 12, flexWrap: 'wrap', padding: '16px 0 4px' }}>
          <div>
            <div className="i-eyebrow"><i></i>Executive Briefing</div>
            <div style={{ fontSize: 19, fontWeight: 800, letterSpacing: '-.03em', color: 'var(--iInk)', marginTop: 6 }}>
              {ctx.period.label}{ctx.cmpPeriod ? ' vs ' + ctx.cmpPeriod.label : ''}
            </div>
          </div>
          <div style={{ display: 'flex', gap: 6 }}>
            <button className="i-ctl" onClick={copyBrief}>
              <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><rect x="9" y="9" width="12" height="12" rx="2" /><path d="M5 15V5a2 2 0 012-2h10" /></svg>Copy
            </button>
            <button className="i-ctl" onClick={() => window.print()}>
              <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M6 9V2h12v7" /><rect x="6" y="14" width="12" height="8" /><path d="M6 18H4a2 2 0 01-2-2v-3a2 2 0 012-2h16a2 2 0 012 2v3a2 2 0 01-2 2h-2" /></svg>Print
            </button>
          </div>
        </div>
        <div className="st-brief">
          {bundle.story.map((s, i) => (
            <div className="st-brief-sec" key={i} style={{ animationDelay: (i * 90) + 'ms' }}>
              <div className="st-brief-h">{s.h}</div>
              <p className="st-brief-p">{s.body}</p>
            </div>
          ))}
        </div>
      </div>

      <StSec title="Board pack" sub="The same conclusions as numbers — the four exhibits a review meeting actually asks for.">
        <div className="i-grid i-g2">
          <div className="i-card">
            <div className="i-card-hd"><div><div className="i-card-t">Profit build-up</div><div className="i-card-s">Single source of truth — Profit Engine</div></div></div>
            <window.IC.Waterfall height={230} steps={[
              { label: 'Revenue', short: 'Revenue', value: ctx.cur.revenue, color: '#16A34A' },
              { label: 'Purchase', short: 'Purchase', value: -ctx.cur.purchaseValue, color: '#DC2626' },
              { label: 'Transport', short: 'Transport', value: -ctx.cur.transportCost, color: '#DC2626' },
              { label: 'Diesel Margin', short: 'Diesel', value: ctx.cur.dieselMargin, color: '#F97316' },
              { label: 'Net Profit', short: 'Net', value: ctx.cur.netProfit, color: ctx.cur.netProfit >= 0 ? '#15803D' : '#DC2626', total: true },
            ]} />
          </div>
          <div className="i-card">
            <div className="i-card-hd"><div><div className="i-card-t">Health composite</div><div className="i-card-s">{ctx.health.grade} · {ctx.health.score} / 100</div></div></div>
            <div style={{ display: 'flex', gap: 16, alignItems: 'center', flexWrap: 'wrap' }}>
              <window.IC.Gauge value={ctx.health.score} size={170} label={ctx.health.grade} sub="composite" />
              <div className="i-hp" style={{ flex: 1, minWidth: 180 }}>
                {ctx.health.parts.map(p => (
                  <div className="i-hp-row" key={p.key}>
                    <div className="i-hp-top"><span className="i-hp-l">{p.label}</span><span className="i-hp-v">{p.score.toFixed(0)}</span></div>
                    <div className="i-hp-track"><div className="i-hp-fill" style={{ width: p.score + '%', background: p.score >= 70 ? '#16A34A' : p.score >= 45 ? '#F97316' : '#DC2626' }}></div></div>
                  </div>
                ))}
              </div>
            </div>
          </div>
          <div className="i-card">
            <div className="i-card-hd"><div><div className="i-card-t">Top opportunities</div><div className="i-card-s">Annualised value, ranked</div></div></div>
            {bundle.op.length ? <window.IC.Rank valueKind="cur" limit={6} rows={bundle.op.map(o => ({ label: o.title, value: o.value, sub: o.confidence + '% confidence' }))} /> : <StEmpty title="None found" msg="No quantifiable opportunity in this window." />}
          </div>
          <div className="i-card">
            <div className="i-card-hd"><div><div className="i-card-t">Top exposures</div><div className="i-card-s">Risk score out of 100</div></div></div>
            {bundle.rk.length ? <window.IC.Rank valueKind="int" limit={6} max={100} colorFor={() => '#DC2626'} rows={bundle.rk.map(r => ({ label: r.title, value: r.score, sub: window.IC.short(r.impact) + ' exposure' }))} /> : <StEmpty title="None found" msg="No measurable exposure in this window." />}
          </div>
        </div>
      </StSec>
    </div>
  );
}

Object.assign(window, { StudioCorrelation, StudioBriefing, StScatter });
