/* OM GROUP ERP — Diesel Recovery · interactive trend + period drill-down
   ─────────────────────────────────────────────────────────────────────────
   Presentation only. Every number rendered here is read out of the pack that
   IntelDomains.build() derives from Store on each ERP write:
       pack.points[i].m     → the metrics of that bucket (dieselCost,
                              dieselRecoverable, dieselRecovered,
                              dieselUnrecovered, dieselRecoveryRate, …)
       pack.points[i].rows  → the very records those metrics were summed from
                              (head === 'Diesel', each carrying .raw = the
                              live diesel record)
   No dataset is created, cached or copied here, so create / edit / delete /
   settle / company / date-range all propagate with the normal rebuild. A
   metric the records cannot support renders as an em dash with its reason —
   never as a fabricated 100%.                                             */

const { useState: drSt, useMemo: drMemo, useEffect: drEf, useRef: drRef } = React;
const DR_MON = ['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC'];
const drN = v => { const n = Number(v); return isFinite(n) ? n : 0; };
const drShort = v => window.IC.short(drN(v));
const drCur = v => window.IC.cur(drN(v));
const drLtr = v => (window.fmtDieselQty ? window.fmtDieselQty(drN(v)) : drN(v).toFixed(2)) + ' L';
function drDay(iso) {
  const p = String(iso || '').slice(0, 10).split('-');
  return p.length === 3 ? (+p[2]) + ' ' + (DR_MON[+p[1] - 1] || '') + ' ' + p[0] : String(iso || '');
}
function drRange(pd) {
  if (!pd) return '';
  return pd.from === pd.to ? drDay(pd.from) : drDay(pd.from) + ' – ' + drDay(pd.to);
}
/* the one place this file decides what a period is called */
function drTitle(pt, grain) {
  if (!pt) return '';
  if (grain === 'day' || (pt.period && pt.period.from === pt.period.to)) return drDay(pt.period.from);
  return String(pt.sub || pt.label || '').toUpperCase();
}
function drRate(m) {
  const r = m ? m.dieselRecoveryRate : null;
  return (r == null || !isFinite(Number(r))) ? null : Number(r);
}

/* ══ RECOVERY TREND ═══════════════════════════════════════════════════════
   Grouped bars, one column per bucket. The whole column is the hit area, so
   selecting a period never asks for a pixel-perfect click. Hover highlights,
   click locks; series visibility is a view flag and touches no data.      */
function DRTrend({ points, keys, height, accent, selIdx, onSelect, grain }) {
  const H = height || 276;
  const [w, wrap] = window.IC.useWidth(700);
  const vis = keys.filter(k => !k.off);
  const [t, animRef] = window.IC.useAnim(JSON.stringify([points.map(p => p.label), points.map(p => keys.map(k => drN(p.m[k.key]))), vis.map(k => k.key)]), 820);
  const [hi, setHi] = drSt(null);
  const [kb, setKb] = drSt(false);
  const n = points.length;
  const padL = 56, padR = 12, padT = 18, padB = 30;
  const iw = Math.max(40, w - padL - padR), ih = Math.max(40, H - padT - padB);
  const slot = n ? iw / n : iw;
  const tops = points.map(p => Math.max.apply(null, vis.length ? vis.map(k => drN(p.m[k.key])) : [0]));
  const rawMax = Math.max.apply(null, tops.length ? tops : [0]);
  const max = rawMax > 0 ? rawMax * 1.16 : 1;
  const bw = Math.max(3, Math.min(30, (slot * 0.66) / Math.max(1, vis.length)));
  const Y = v => padT + ih - (Math.max(0, drN(v)) / max) * ih;
  const ticks = [0, .25, .5, .75, 1].map(f => max * f);
  const step = Math.max(1, Math.ceil(n / Math.max(3, Math.floor(w / 72))));
  const xTicks = drMemo(() => window.IC.pickTicks(n, step), [n, step]);

  const recCount = p => (p.rows || []).filter(r => r.head === 'Diesel').length;
  function tip(e, i) {
    const p = points[i]; const r = drRate(p.m); const c = recCount(p);
    window.ICTooltip.show(e, {
      title: drTitle(p, grain) + (p.sub ? ' · ' + p.sub : ''),
      rows: vis.map(k => ({ dot: k.color, k: k.label, v: drShort(p.m[k.key]), color: k.color }))
        .concat([{ k: 'Recovery', v: r == null ? 'not measurable' : r.toFixed(1) + '%' },
        { k: 'Records', v: String(c) }]),
      foot: c ? (selIdx === i ? 'Selected · click to reopen the breakdown' : 'Click for the full breakdown') : 'No diesel recorded in this period',
    }, { avoidRect: wrap.current && wrap.current.getBoundingClientRect(), axisBand: padB });
  }
  function move(d) {
    if (!n) return;
    const base = hi == null ? (selIdx == null ? 0 : selIdx) : hi;
    const i = Math.min(n - 1, Math.max(0, base + d));
    setKb(true); setHi(i);
  }
  function key(e) {
    if (e.key === 'ArrowRight') { move(1); e.preventDefault(); }
    else if (e.key === 'ArrowLeft') { move(-1); e.preventDefault(); }
    else if (e.key === 'Home') { setKb(true); setHi(0); e.preventDefault(); }
    else if (e.key === 'End') { setKb(true); setHi(n - 1); e.preventDefault(); }
    else if (e.key === 'Enter' || e.key === ' ') { if (hi != null && onSelect) onSelect(hi); e.preventDefault(); }
  }
  if (!n) return <window.IC.Empty h={H} msg="No periods in the selected range" />;
  if (!vis.length) return (
    <div className="dr-allhidden" style={{ height: H }}>
      <b>All four series are hidden</b>
      <span>Turn a series back on in the legend above. Nothing was removed — the calculation is untouched.</span>
    </div>
  );
  return (
    <div ref={wrap} className="dr-chart" tabIndex={0} role="group"
      aria-label={'Recovery trend, ' + n + ' periods. Arrow keys move between periods, Enter opens the breakdown.'}
      onKeyDown={key} onBlur={() => { setKb(false); setHi(null); }}>
      <div ref={animRef}>
        <svg width="100%" height={H} viewBox={'0 0 ' + w + ' ' + H} style={{ display: 'block', overflow: 'visible' }}>
          {ticks.map((v, i) => (<g key={i}>
            <line x1={padL} x2={padL + iw} y1={Y(v)} y2={Y(v)} stroke={i === 0 ? '#E5E3E0' : '#F1EFEC'} />
            <text x={padL - 9} y={Y(v) + 3.5} textAnchor="end" fontSize="9.5" fill="#A8A4A0" fontWeight="500">{drShort(v)}</text>
          </g>))}
          {points.map((p, i) => {
            const sel = selIdx === i, hov = hi === i;
            const cx = padL + slot * i + slot / 2;
            const gw = vis.length * bw + (vis.length - 1) * 3;
            return (
              <g key={i} className={'dr-col' + (sel ? ' sel' : '')}
                onMouseEnter={() => { setKb(false); setHi(i); }}
                onMouseLeave={() => { if (!kb) setHi(null); window.ICTooltip.hide(); }}
                onMouseMove={e => tip(e, i)}
                onClick={() => onSelect && onSelect(i)} style={{ cursor: 'pointer' }}>
                <rect x={padL + slot * i + 1} y={padT - 8} width={Math.max(2, slot - 2)} height={ih + 14} rx="7"
                  fill={sel ? accent + '12' : hov ? '#FAF9F7' : 'transparent'}
                  stroke={sel ? accent + '3D' : 'transparent'} style={{ transition: 'fill .18s, stroke .18s' }} />
                {vis.map((k, ki) => {
                  const v = drN(p.m[k.key]); const y = Y(v); const h = (padT + ih - y) * t;
                  return <rect key={k.key} x={cx - gw / 2 + ki * (bw + 3)} y={padT + ih - h} width={bw} height={Math.max(0, h)} rx="3" fill={k.color}
                    style={{ transition: 'opacity .18s', opacity: hi != null && !hov && !sel ? 0.36 : 1, filter: hov || sel ? 'drop-shadow(0 4px 11px ' + k.color + '55)' : null }} />;
                })}
                {sel && <rect x={padL + slot * i + Math.max(2, slot - 2) * 0.22} y={padT + ih + 3} width={Math.max(6, Math.max(2, slot - 2) * 0.56)} height="2.5" rx="1.25" fill={accent} />}
              </g>
            );
          })}
          {points.map((p, i) => {
            const sel = selIdx === i, hov = hi === i;
            if (!xTicks.has(i)) return null;
            return <text key={i} x={padL + slot * i + slot / 2} y={H - 9} textAnchor="middle" fontSize="9.5"
              fontWeight={sel || hov ? 800 : 500} fill={sel ? accent : hov ? '#1A1917' : '#A8A4A0'}>{p.label}</text>;
          })}
        </svg>
      </div>
    </div>
  );
}

/* ══ PERIOD BREAKDOWN ═════════════════════════════════════════════════════
   Everything below is read live from pack.points[idx]; the sheet holds no
   copy of it, so an edit behind it lands on the next render.              */
function DRFact({ k, v, tone }) {
  return <div className="dr-fact"><span>{k}</span><b style={tone ? { color: tone } : null}>{v}</b></div>;
}
function DRPeriodSheet({ pack, spec, idx, grain, onClose, onNav, onDrill, overridePt, wholePeriod }) {
  const pt = overridePt || pack.points[idx];
  const closeRef = drRef(null);
  drEf(() => {
    const h = e => {
      if (e.key === 'Escape') { onClose(); }
      else if (!wholePeriod && e.key === 'ArrowRight') { onNav(1); }
      else if (!wholePeriod && e.key === 'ArrowLeft') { onNav(-1); }
    };
    document.addEventListener('keydown', h);
    if (closeRef.current) closeRef.current.focus();
    return () => document.removeEventListener('keydown', h);
  }, [idx, onClose, onNav]);
  if (!pt) return null;

  const m = pt.m || {};
  /* the sheet is portaled to <body>: any transformed / filtered ancestor in
     the analytics page would otherwise become its containing block and the
     centred overlay could land outside the viewport. */
  const recs = (pt.rows || []).filter(r => r.head === 'Diesel');
  const cost = drN(m.dieselCost), able = drN(m.dieselRecoverable), got = drN(m.dieselRecovered), open = drN(m.dieselUnrecovered);
  const rate = drRate(m);
  const litres = recs.reduce((s, r) => s + drN(r.qty), 0);
  const uniq = fn => { const o = {}; recs.forEach(r => { const v = fn(r); if (v) o[String(v).trim()] = 1; }); return Object.keys(o); };
  const transporters = uniq(r => (r.raw && (r.raw.transporterName || r.raw.transporterId)) || (r.party !== '—' ? r.party : ''));
  const vehicles = uniq(r => r.raw && r.raw.vehicleFull);
  const vendors = uniq(r => r.raw && r.raw.allocVendorId).map(id => (window.Store && window.Store.name('vendors', id)) || id);
  const settlements = uniq(r => r.raw && r.raw.settledInSettlementId).length + uniq(r => r.raw && r.raw.vendorSettledInId).length;
  const stat = {}; recs.forEach(r => { stat[r.status] = (stat[r.status] || 0) + 1; });
  const noDed = recs.filter(r => drN(r.recoverable) <= 0);
  const noDedAmt = noDed.reduce((s, r) => s + drN(r.value), 0);
  const bad = got > able + 0.01;
  const pct = able > 0 ? Math.max(0, Math.min(100, got / able * 100)) : 0;
  const company = !pack.companyId || pack.companyId === 'group' ? 'OM Group (All Companies)'
    : (window.Store && window.Store.name('companies', pack.companyId)) || 'Selected company';
  const cfN = pack.cf ? Object.keys(pack.cf).filter(k => pack.cf[k] != null && pack.cf[k] !== '' && pack.cf[k] !== 'all').length : 0;
  const accent = spec.color;
  const kpis = [
    { k: 'Diesel Cost', v: cost, c: '#F97316', s: 'Paid to the pump' },
    { k: 'Recoverable Diesel', v: able, c: '#2563EB', s: 'Deduction raised' },
    { k: 'Diesel Recovered', v: got, c: '#16A34A', s: 'Inside a settled settlement' },
  ];
  return ReactDOM.createPortal((
    <div className="dr-bg" onMouseDown={e => { if (e.target === e.currentTarget) onClose(); }}>
      <div className="dr-sheet" role="dialog" aria-modal="true" aria-label={'Diesel recovery, ' + drTitle(pt, grain)} style={{ '--drA': accent }}>
        <div className="dr-hd">
          <div className="dr-hd-t">
            <div className="dr-eyebrow"><i></i>Diesel Recovery</div>
            <div className="dr-hd-date">{drTitle(pt, grain)}</div>
            <div className="dr-hd-sub">{wholePeriod ? 'Full period selection' : (String(pack.grain || '').charAt(0).toUpperCase() + String(pack.grain || '').slice(1) + ' bucket')}{pt.period.from !== pt.period.to ? ' · ' + drRange(pt.period) : ''} · {recs.length} diesel record{recs.length === 1 ? '' : 's'}</div>
          </div>
          <div className="dr-hd-nav">
            <button className="dr-ico" onClick={() => onNav(-1)} disabled={wholePeriod || idx <= 0} title="Previous period (←)" aria-label="Previous period">
              <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4"><path d="M15 6l-6 6 6 6" /></svg></button>
            <button className="dr-ico" onClick={() => onNav(1)} disabled={wholePeriod || idx >= pack.points.length - 1} title="Next period (→)" aria-label="Next period">
              <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4"><path d="M9 6l6 6-6 6" /></svg></button>
            <button className="dr-ico x" ref={closeRef} onClick={onClose} title="Close (Esc)" aria-label="Close">
              <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4"><path d="M6 6l12 12M18 6L6 18" /></svg></button>
          </div>
        </div>
        <div className="dr-bd">
          {!recs.length ? (
            <div className="dr-none">
              <b>No diesel recorded in this period</b>
              <span>Nothing was paid to a pump inside {drRange(pt.period)} for {company}. The column is shown so the timeline stays continuous — no record is invented for it.</span>
            </div>
          ) : (
            <React.Fragment>
              <div className="dr-hero">
                <div className="dr-hero-main">
                  <span>Unrecovered Diesel</span>
                  <b><window.IC.Num value={open} kind="cur" /></b>
                  <em>{able > 0 ? 'Raised against a transporter or vendor and still unsettled' : 'No deduction has been raised against this diesel'}</em>
                </div>
                <div className="dr-hero-rate">
                  <div className="dr-hero-rate-top">
                    <span>Recovery Rate</span>
                    <b style={{ color: rate == null ? 'var(--iInk3)' : rate >= 60 ? '#15803D' : rate > 0 ? '#B45309' : '#B91C1C' }}>
                      {rate == null ? '—' : rate.toFixed(1) + '%'}</b>
                  </div>
                  <div className="dr-track"><i style={{ width: pct + '%' }}></i></div>
                  <div className="dr-hero-rate-ft">
                    {rate == null
                      ? 'Not applicable — nothing recoverable in this period, so the ratio is undefined, not 0%.'
                      : drCur(got) + ' recovered of ' + drCur(able) + ' recoverable'}
                  </div>
                </div>
              </div>
              {bad && (
                <div className="dr-warn">
                  <b>Data inconsistency</b>
                  <span>{drCur(got)} is shown as recovered against a recoverable base of {drCur(able)}. A settlement is carrying more diesel than the deduction raised for this period — check the linked settlements on these records.</span>
                </div>
              )}
              <div className="dr-kpis">
                {kpis.map(k => (
                  <div className="dr-kpi" key={k.k} style={{ '--kc': k.c }}>
                    <span>{k.k}</span>
                    <b><window.IC.Num value={k.v} kind="cur" /></b>
                    <em>{k.s}</em>
                  </div>
                ))}
              </div>
              <div className="dr-sub-t">Derived from the {recs.length} record{recs.length === 1 ? '' : 's'} in this period</div>
              <div className="dr-facts">
                <DRFact k="Diesel records" v={recs.length} />
                {litres > 0 && <DRFact k="Total litres" v={drLtr(litres)} />}
                {transporters.length > 0 && <DRFact k="Transporters" v={transporters.length} />}
                {vehicles.length > 0 && <DRFact k="Vehicles" v={vehicles.length} />}
                {vendors.length > 0 && <DRFact k="Vendors" v={vendors.length} />}
                {settlements > 0 && <DRFact k="Linked settlements" v={settlements} />}
                {noDed.length > 0 && <DRFact k="Outside recoverable base" v={drCur(noDedAmt)} tone="#B45309" />}
              </div>
              <div className="dr-chips">
                {Object.keys(stat).map(s => (
                  <span key={s} className={'dr-chip ' + (s === 'Recovered' ? 'ok' : s === 'Partly recovered' ? 'wa' : s === 'Recoverable' ? 'dn' : '')}>
                    {s}<i>{stat[s]}</i></span>
                ))}
              </div>
              <div className="dr-sub-t">Records</div>
              <div className="dr-tbl-wrap">
                <table className="i-dl-tbl dr-tbl">
                  <thead><tr>
                    <th>Date</th><th>Bill</th><th>Transporter</th><th>Vehicle</th>
                    <th className="r">Litres</th><th className="r">Cost</th><th className="r">Recoverable</th><th className="r">Recovered</th><th>Status</th>
                  </tr></thead>
                  <tbody>
                    {recs.map(r => (
                      <tr key={r.id}>
                        <td>{drDay(r.date)}</td>
                        <td>{r.ref || '—'}</td>
                        <td>{r.party || '—'}</td>
                        <td>{(r.raw && r.raw.vehicleFull) || '—'}</td>
                        <td className="r">{drN(r.qty) > 0 ? drLtr(r.qty) : '—'}</td>
                        <td className="r">{drCur(r.value)}</td>
                        <td className="r">{drN(r.recoverable) > 0 ? drCur(r.recoverable) : '—'}</td>
                        <td className="r" style={{ color: drN(r.recovered) > 0 ? '#15803D' : 'var(--iInk3)' }}>{drN(r.recovered) > 0 ? drCur(r.recovered) : '—'}</td>
                        <td><span className={'dr-chip sm ' + (r.status === 'Recovered' ? 'ok' : r.status === 'Partly recovered' ? 'wa' : r.status === 'Recoverable' ? 'dn' : '')}>{r.status}</span></td>
                      </tr>
                    ))}
                  </tbody>
                  <tfoot><tr>
                    <td colSpan="4">{recs.length} record{recs.length === 1 ? '' : 's'}</td>
                    <td className="r">{litres > 0 ? drLtr(litres) : '—'}</td>
                    <td className="r">{drCur(cost)}</td>
                    <td className="r">{drCur(able)}</td>
                    <td className="r">{drCur(got)}</td>
                    <td></td>
                  </tr></tfoot>
                </table>
              </div>
            </React.Fragment>
          )}
        </div>
        <div className="dr-ft">
          <span>{company} · {drRange(pt.period)}{cfN ? ' · ' + cfN + ' filter' + (cfN === 1 ? '' : 's') + ' applied' : ''} · live from the diesel records</span>
          {!!recs.length && <button className="dr-btn" onClick={() => { onDrill && onDrill(); onClose(); }}>Open these records in the ledger</button>}
        </div>
      </div>
    </div>
  ), document.body);
}

Object.assign(window, { DRTrend, DRPeriodSheet, drTitle, drRange, drDay });
