/* ══ OM Group ERP — Analysis Studio · Opportunity Scanner & Risk Center ═══
   Two ranked registers computed live: where money is being left on the table,
   and where it is exposed. Every entry carries the arithmetic, its evidence,
   a recommended action and a one-tap route into the underlying records.

   Both panels share one exposure figure — a matched pair of radars built by
   StudioExposure from the same dimension evaluator, scored two ways. An axis
   appears on either chart only when the metric behind it exists in the
   current scope, so the shape of the chart is itself a statement about the
   data, never a fixed template.                                          */
const { useState: opSt, useMemo: opMemo } = React;

const OP_CAT_COLOR = { Margin: '#F97316', Pricing: '#7C3AED', Cash: '#0891B2', Demand: '#16A34A', Inventory: '#CA8A04', Operations: '#2563EB' };
const RK_BAND_COLOR = { critical: '#DC2626', elevated: '#EA580C', watch: '#CA8A04' };
const EXP_RISK = '#DC2626', EXP_OPP = '#16A34A';

function StCard({ color, title, value, valueLabel, detail, meters, evidence, action, onOpen, actionIcon }) {
  const [open, setOpen] = opSt(false);
  return (
    <div className="st-op" style={{ '--oc': color }} onClick={() => setOpen(o => !o)}>
      <div className="st-op-hd">
        <div className="st-op-t">{title}</div>
        {value != null && <div className="st-op-val"><b>{value}</b><span>{valueLabel}</span></div>}
      </div>
      <div className="st-op-d">{detail}</div>
      <div className="st-op-ft">{meters}</div>
      {open && (
        <div>
          <ul className="st-op-ev">{evidence.map((e, i) => <li key={i}>{e}</li>)}</ul>
          {action && (
            <div className="st-op-act">
              {actionIcon || (window.OMIcon ? <window.OMIcon name="bulb" size={13} /> : null)}
              <span>{action}</span>
            </div>
          )}
          {onOpen && (
            <button className="i-ctl" style={{ marginTop: 10 }} onClick={e => { e.stopPropagation(); onOpen(); }}>
              {window.OMIcon ? <window.OMIcon name="grid" size={13} /> : null}Open the records behind this
            </button>
          )}
        </div>
      )}
      {!open && <div className="st-op-more" style={{ marginTop: 9, fontSize: 10, fontWeight: 700, color: color }}>Tap for evidence and the recommended action →</div>}
    </div>
  );
}

/* ── one exposure radar — the shell both charts share verbatim ─────────── */
function StExpoCard({ kind, dims, index, cap, onCap, capped }) {
  const isRisk = kind === 'risk';
  const color = isRisk ? EXP_RISK : EXP_OPP;
  const key = isRisk ? 'risk' : 'opp';
  const shown = dims.slice(0, cap);
  const band = index >= 60 ? (isRisk ? 'Severe' : 'Exceptional') : index >= 35 ? (isRisk ? 'Elevated' : 'Strong') : index >= 15 ? (isRisk ? 'Contained' : 'Moderate') : (isRisk ? 'Low' : 'Thin');
  if (!shown.length) {
    return (
      <div className="i-card i-expo">
        <div className="i-card-hd"><div style={{ display: 'flex', gap: 9, alignItems: 'center' }}>
          <span className="i-ico" style={{ '--ic': color }}>{window.OMIcon ? <window.OMIcon name={isRisk ? 'shield' : 'trendUp'} size={15} /> : null}</span>
          <div><div className="i-card-t">{isRisk ? 'Risk Exposure' : 'Opportunity Exposure'}</div><div className="i-card-s">No measurable dimension in this window</div></div>
        </div></div>
        <window.IC.Empty h={200} msg="Widen the period or clear a filter" />
      </div>
    );
  }
  return (
    <div className="i-card i-expo">
      <div className="i-card-hd">
        <div style={{ display: 'flex', gap: 9, alignItems: 'center', minWidth: 0 }}>
          <span className="i-ico" style={{ '--ic': color }}>{window.OMIcon ? <window.OMIcon name={isRisk ? 'shield' : 'trendUp'} size={15} /> : null}</span>
          <div style={{ minWidth: 0 }}>
            <div className="i-card-t">{isRisk ? 'Risk Exposure' : 'Opportunity Exposure'}</div>
            <div className="i-card-s">{shown.length} of {dims.length} live dimension{dims.length === 1 ? '' : 's'} · scored 0–100</div>
          </div>
        </div>
        <div className="i-expo-idx" style={{ '--ec': color }}><b>{index}</b><span>{band}</span></div>
      </div>
      <window.IC.Radar height={286}
        axes={shown.map(d => d.label)}
        notes={shown.map(d => d.note)}
        series={[{ label: isRisk ? 'Risk score' : 'Upside score', color: color, values: shown.map(d => d[key]) }]} />
      <div className="i-expo-legend">
        {shown.slice(0, 3).map(d => (
          <div className="i-expo-row" key={d.id} title={d.note}>
            <span>{d.label}</span>
            <i><b style={{ width: Math.round(d[key] * 100) + '%', background: color }}></b></i>
            <em>{Math.round(d[key] * 100)}</em>
          </div>
        ))}
      </div>
      {dims.length > 6 && (
        <button className="i-ctl sm" style={{ marginTop: 10 }} onClick={onCap}>{capped ? 'Show all ' + dims.length + ' dimensions' : 'Show the top 9 only'}</button>
      )}
    </div>
  );
}

/* both charts, identical shell, side by side — used by BOTH panels */
function StExposureCharts({ ctx, risks, opps }) {
  const ex = opMemo(() => (window.StudioExposure ? window.StudioExposure.build(ctx, risks, opps) : { risk: [], opp: [], riskIndex: 0, oppIndex: 0 }), [ctx, risks, opps]);
  const [capped, setCapped] = opSt(true);
  const cap = capped ? 9 : 99;
  if (!ex.risk.length && !ex.opp.length) return null;
  return (
    <div className="i-grid i-g2 i-expo-grid">
      <StExpoCard kind="risk" dims={ex.risk} index={ex.riskIndex} cap={cap} capped={capped} onCap={() => setCapped(c => !c)} />
      <StExpoCard kind="opp" dims={ex.opp} index={ex.oppIndex} cap={cap} capped={capped} onCap={() => setCapped(c => !c)} />
    </div>
  );
}

function StudioOpportunities({ ctx }) {
  const DEng = window.DecisionEngine;
  const list = opMemo(() => DEng.opportunities(ctx), [ctx]);
  const risks = opMemo(() => { try { return DEng.risks(ctx); } catch (e) { return []; } }, [ctx]);
  const [cat, setCat] = opSt('all');
  const cats = opMemo(() => ['all'].concat(list.map(o => o.category).filter((c, i, a) => a.indexOf(c) === i)), [list]);
  const shown = cat === 'all' ? list : list.filter(o => o.category === cat);
  const total = list.reduce((s, o) => s + o.value, 0);

  if (!list.length) return <StEmpty title="Nothing on the table" msg="The scanner found no quantifiable opportunity in this window. Widen the period or clear a filter — it re-scans instantly." />;

  return (
    <div>
      <p className="st-lede">
        {list.length} quantified opportunit{list.length === 1 ? 'y' : 'ies'} worth <b>{window.IC.short(total)} annualised</b>, ranked by value.
        Each one is arithmetic over live records — tap a card to see the numbers it used and the action it implies.
      </p>

      <div className="st-res" style={{ marginBottom: 12 }}>
        <StRes label="Total identified" value={total} color="#16A34A" note="annualised at current run rates" />
        <StRes label="Largest single" value={list[0].value} color={OP_CAT_COLOR[list[0].category]} note={list[0].category.toLowerCase()} />
        <StRes label="Avg confidence" value={Math.round(list.reduce((s, o) => s + o.confidence, 0) / list.length)} kind="int" color="#7C3AED" note="across all findings" />
        <StRes label="Against net profit" value={ctx.cur.netProfit ? total / Math.abs(ctx.cur.netProfit * DEng.extras(ctx).ann) * 100 : 0} kind="pct" color="#F97316" note="of annualised net profit" />
      </div>

      <StSec title="Exposure profile" icon="target"
        sub="The same dimension set scored two ways. An axis appears only where the underlying metric exists in this scope — upside is measured against what this business already achieved in its best bucket, never an invented benchmark.">
        <StExposureCharts ctx={ctx} risks={risks} opps={list} />
      </StSec>

      <div className="st-filters">
        {cats.map(c => <button key={c} className={'i-ctl sm' + (cat === c ? ' on' : '')} onClick={() => setCat(c)}>
          {c === 'all' ? 'All ' + list.length : c + ' ' + list.filter(o => o.category === c).length}</button>)}
      </div>

      <div className="i-grid i-g2">
        {shown.map(o => (
          <StCard key={o.id} color={OP_CAT_COLOR[o.category] || '#F97316'}
            title={o.title} value={window.IC.short(o.value)} valueLabel="per year"
            detail={o.detail}
            meters={<React.Fragment>
              <StTag level={o.confidence >= 70 ? 'lo' : o.confidence >= 50 ? 'md' : 'hi'}>{o.confidence}% confidence</StTag>
              <StTag>{o.category}</StTag>
              <StMeter label="evidence strength" pct={o.confidence} color={OP_CAT_COLOR[o.category]} />
            </React.Fragment>}
            evidence={o.evidence} action={o.action}
            onOpen={o.cf ? () => { ctx.push({ kind: 'explore', label: o.cfLabel || o.title, period: ctx.period, cf: Object.assign({}, ctx.cf, o.cf) }); } : null} />
        ))}
      </div>
    </div>
  );
}

function StudioRisks({ ctx }) {
  const DEng = window.DecisionEngine;
  const list = opMemo(() => DEng.risks(ctx), [ctx]);
  const opps = opMemo(() => { try { return DEng.opportunities(ctx); } catch (e) { return []; } }, [ctx]);
  const [band, setBand] = opSt('all');
  const shown = band === 'all' ? list : list.filter(r => r.band === band);
  const exposure = list.reduce((s, r) => s + r.impact, 0);
  const crit = list.filter(r => r.band === 'critical').length;

  if (!list.length) return <StEmpty title="No measurable exposure" msg="The risk engine found nothing above its noise floor in this window. That is unusual — widen the period to see structural exposure." />;

  return (
    <div>
      <p className="st-lede">
        {list.length} monitored exposure{list.length === 1 ? '' : 's'} carrying <b>{window.IC.short(exposure)}</b> of annualised financial impact.
        {crit > 0 ? ' ' + crit + ' scored critical.' : ' None currently scored critical.'} Score blends likelihood and impact — both computed, neither assumed.
      </p>

      <div className="st-res" style={{ marginBottom: 12 }}>
        <StRes label="Total exposure" value={exposure} color="#DC2626" good="down" note="annualised financial impact" />
        <StRes label="Highest score" value={list[0].score} kind="int" color={RK_BAND_COLOR[list[0].band]} good="down" note={list[0].category.toLowerCase()} />
        <StRes label="Critical" value={crit} kind="int" color="#DC2626" good="down" note={'of ' + list.length + ' monitored'} />
        <StRes label="Against revenue" value={ctx.cur.revenue ? exposure / (ctx.cur.revenue * DEng.extras(ctx).ann) * 100 : 0} kind="pct" color="#EA580C" good="down" note="of annualised revenue" />
      </div>

      <StSec title="Exposure profile" icon="shield"
        sub="Risk and opportunity on the same dimension set, drawn with the same geometry so the two shapes can be read against each other. Every axis is a live metric; anything the current scope cannot measure is absent rather than zeroed.">
        <StExposureCharts ctx={ctx} risks={list} opps={opps} />
      </StSec>

      <div className="st-filters">
        {['all', 'critical', 'elevated', 'watch'].map(b => {
          const n = b === 'all' ? list.length : list.filter(r => r.band === b).length;
          if (!n) return null;
          return <button key={b} className={'i-ctl sm' + (band === b ? ' on' : '')} style={{ textTransform: 'capitalize' }} onClick={() => setBand(b)}>{b} {n}</button>;
        })}
      </div>

      <div className="i-grid i-g2">
        {shown.map(r => (
          <StCard key={r.id} color={RK_BAND_COLOR[r.band]}
            title={r.title} value={String(r.score)} valueLabel="risk score"
            detail={r.detail}
            meters={<React.Fragment>
              <StTag level={r.band === 'critical' ? 'hi' : r.band === 'elevated' ? 'md' : 'lo'}>{r.band}</StTag>
              <StTag>{r.category}</StTag>
              <StMeter label={'likelihood ' + Math.round(r.likelihood * 100) + '%'} pct={r.likelihood * 100} color={RK_BAND_COLOR[r.band]} />
              <span style={{ fontSize: 10, fontWeight: 700, color: 'var(--iInk2)' }}>impact {window.IC.short(r.impact)}</span>
            </React.Fragment>}
            evidence={r.why} action={r.action}
            actionIcon={window.OMIcon ? <window.OMIcon name="warn" size={13} /> : null}
            onOpen={r.cf ? () => { ctx.push({ kind: 'explore', label: r.cfLabel || r.title, period: ctx.period, cf: Object.assign({}, ctx.cf, r.cf) }); } : null} />
        ))}
      </div>
    </div>
  );
}

Object.assign(window, { StudioOpportunities, StudioRisks, StCard, StExposureCharts, StExpoCard });
