/* OM Group ERP — Intelligence Center sections.
   Every section is a pure view over the ctx built by IntelCenterPage; all of
   them read the same live dataset, so a change anywhere in the ERP moves
   every number, chart, ranking, forecast and insight together.            */
const { useState: isSt, useEffect: isEf, useMemo: isMemo, useRef: isRef } = React;
const IEg = window.IntelEngine;

function useInView(){
  const ref=isRef(null); const [seen,setSeen]=isSt(false);
  isEf(()=>{
    const el=ref.current; if(!el) return;
    if(!('IntersectionObserver' in window)){ setSeen(true); return; }
    const io=new IntersectionObserver(es=>es.forEach(e=>{ if(e.isIntersecting){ setSeen(true); io.disconnect(); } }),{threshold:0.06});
    io.observe(el); return ()=>io.disconnect();
  },[]);
  return [ref,seen];
}
function ISection({ id, title, sub, right, children, anchor, icon }){
  const [ref,seen]=useInView();
  return (
    <section ref={ref} id={anchor} className={'i-sec'+(seen?' in':'')} data-screen-label={title}>
      <div className="i-sec-hd">
        <div><div className="i-sec-t">{window.OMSecIcon?<window.OMSecIcon name={icon} title={typeof title==='string'?title:''}/>:<span className="i-dot"></span>}{title}</div>{sub&&<div className="i-sec-s">{sub}</div>}</div>
        {right}
      </div>
      {children}
    </section>
  );
}

const isArrow = d => d>0
  ? <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3"><path d="M7 17L17 7M17 7H9M17 7v8"/></svg>
  : d<0 ? <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3"><path d="M7 7l10 10M17 17H9M17 17V9"/></svg>
  : <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3"><path d="M5 12h14"/></svg>;

function ISDelta({ cur, prev, good }){
  if(prev==null) return <span className="i-kpi-cmp">no comparison</span>;
  const d = prev!==0 ? (cur-prev)/Math.abs(prev)*100 : (cur>0?100:0);
  const better = good==='down' ? d<0 : good==='flat' ? true : d>0;
  const cls = Math.abs(d)<0.05 ? 'fl' : (good==='flat' ? 'fl' : better?'up':'dn');
  return <span className={'i-delta '+cls}>{isArrow(Math.abs(d)<0.05?0:d)}{Math.abs(d)>999?'>999':Math.abs(d).toFixed(1)}%</span>;
}

/* ══ KPI RAIL ══════════════════════════════════════════════════════════════
   Every card opens the traceable KPI sheet for its own metric: the same
   metric function, re-run over the same live dataset, down to the records. */
const ISK_ARROW = (
  <span className="i-kpi-more" aria-hidden="true">
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.6" strokeLinecap="round" strokeLinejoin="round"><path d="M7 17L17 7M17 7H9M17 7v8" /></svg>
  </span>
);
/* native (Sales / Purchase) KPI sheet host — one implementation shared by the
   rail and the comparison table */
function ISKpiSheet({ ctx, mkey, onClose, onMetric }){
  const app = React.useContext(window.AppCtx) || {};
  if(!window.KpiSheetGuard || !window.KpiIntel) return null;
  const nctx = { companyId: ctx.companyId, mode: ctx.mode, period: ctx.period, cmpPeriod: ctx.cmpPeriod,
    cf: ctx.cf, ds: ctx.ds, cur: ctx.cur, prev: ctx.prev, points: ctx.ser ? ctx.ser.points : [] };
  return (
    <window.KpiSheetGuard metricKey={mkey} build={()=>window.KpiIntel.nativeModel(mkey, nctx)}
      onClose={onClose} onMetric={onMetric}
      onNavigate={page=>{ onClose(); app.navigate && app.navigate(page); }} />
  );
}
function ISKpis({ ctx }){
  const { cur, prev, ser, mode } = ctx;
  const keys = IEg.HERO[mode];
  const color = window.IC.MODE_COLOR[mode];
  const [drill,setDrill]=isSt(null);
  return (
    <div className="i-kpis">
      {keys.map((k,i)=>{
        const meta=IEg.METRICS[k];
        const spark=ser.points.map(p=>p.m[k]);
        const kc = i===0?color : meta.good==='down' ? '#2563EB' : '#16A34A';
        return (
          <div className="i-kpi" key={k} role="button" tabIndex={0}
               aria-label={'Open '+meta.label+' detailed analysis'}
               title={'Open '+meta.label+' — calculation, contributors and source records'}
               style={{'--kc':kc,animation:'iRow .5s '+(i*45)+'ms cubic-bezier(.16,1,.3,1) both'}}
               onClick={()=>setDrill(k)}
               onKeyDown={e=>{ if(e.key==='Enter'||e.key===' '||e.key==='Spacebar'){ e.preventDefault(); setDrill(k); } }}>
            <div className="i-kpi-k">{meta.label}</div>
            <div className="i-kpi-v"><window.IC.Num value={cur[k]} kind={meta.fmt}/></div>
            <div className="i-kpi-ft">
              <ISDelta cur={cur[k]} prev={prev?prev[k]:null} good={meta.good}/>
              <window.IC.Spark values={spark} color={kc} width={62} height={22} area/>
            </div>
            {ISK_ARROW}
          </div>
        );
      })}
      {drill && <ISKpiSheet ctx={ctx} mkey={drill} onClose={()=>setDrill(null)} onMetric={setDrill}/>}
    </div>
  );
}

/* ══ PERFORMANCE TREND ═════════════════════════════════════════════════════ */
function ISPerformance({ ctx }){
  const { ser, cmpSer, mode, period, cmpPeriod, cf, push, grain, setGrain, cur } = ctx;
  const color = window.IC.MODE_COLOR[mode];
  const [metric,setMetric]=isSt(mode==='purchase'?'purchaseValue':'revenue');
  isEf(()=>{ setMetric(mode==='purchase'?'purchaseValue':'revenue'); },[mode]);
  const opts = mode==='purchase' ? ['purchaseValue','qtyPurchased','app','pos'] : ['revenue','grossProfit','qtySold','asp','margin'];
  const meta = IEg.METRICS[metric];
  const series=[{ key:'cur', label:period.label, color, values:ser.points.map(p=>p.m[metric]) }];
  if(cmpSer && cmpSer.points.length){
    const pad=[]; const n=ser.points.length;
    for(let i=0;i<n;i++) pad.push(cmpSer.points[i]?cmpSer.points[i].m[metric]:0);
    series.push({ key:'cmp', label:cmpPeriod.label, color:'#A8A4A0', dashed:true, values:pad });
  }
  const wf = isMemo(()=>{
    if(mode==='purchase') return [
      { label:'Purchase Value', short:'Purchase', value:cur.purchaseValue, color:'#2563EB' },
      { label:'Transport Cost', short:'Transport', value:cur.transportCost, color:'#7C3AED' },
      { label:'Diesel Recovery', short:'Recovery', value:-cur.recovery, color:'#16A34A' },
      { label:'Landed Cost', short:'Landed', value:cur.purchaseValue+cur.transportCost-cur.recovery, color:window.OM_CHART_COLORS.total, total:true },
    ];
    return [
      { label:'Revenue', short:'Revenue', value:cur.revenue, color:'#16A34A' },
      { label:'Purchase', short:'Purchase', value:-cur.purchaseValue, color:'#DC2626' },
      { label:'Transport', short:'Transport', value:-cur.transportCost, color:'#DC2626' },
      { label:'Diesel Margin', short:'Diesel', value:cur.dieselMargin, color:'#F97316' },
      { label:'Net Profit', short:'Net', value:cur.netProfit, color:cur.netProfit>=0?'#15803D':'#DC2626', total:true },
    ];
  },[cur,mode]);
  const GR=[['auto','Auto'],['day','Daily'],['week','Weekly'],['cycle','Cycle'],['month','Monthly'],['quarter','Quarterly']];
  return (
    <ISection title="Business Performance" anchor="i-performance"
      sub={'How '+(mode==='purchase'?'procurement':'trade')+' moved across '+period.label.toLowerCase()+(cmpPeriod?', against '+cmpPeriod.label.toLowerCase():'')+'. Click any point to open that window.'}
      right={<div style={{display:'flex',gap:5,flexWrap:'wrap'}}>{GR.map(g=>(
        <button key={g[0]} className={'i-ctl sm'+(grain===g[0]?' on':'')} onClick={()=>setGrain(g[0])}>{g[1]}</button>))}</div>}>
      <div className="i-grid i-g23">
        <div className="i-card hov">
          <div className="i-card-hd">
            <div><div className="i-card-t">{meta.label} over time</div><div className="i-card-s">{ser.grain} buckets · {ser.points.length} points</div></div>
            <div style={{display:'flex',gap:4,flexWrap:'wrap'}}>{opts.map(o=>(
              <button key={o} className={'i-ctl sm'+(metric===o?' on':'')} onClick={()=>setMetric(o)}>{IEg.METRICS[o].label}</button>))}</div>
          </div>
          <window.IC.Area height={272} yKind={meta.fmt} labels={ser.points.map(p=>p.label)} subLabels={ser.points.map(p=>p.sub)} series={series}
            onPointClick={i=>push({kind:'explore',label:ser.points[i].period.label,period:ser.points[i].period,cf})}/>
        </div>
        <div className="i-card hov">
          <div className="i-card-hd"><div><div className="i-card-t">{mode==='purchase'?'Landed cost build-up':'Profit waterfall'}</div><div className="i-card-s">Single source of truth — Profit Engine</div></div></div>
          <window.IC.Waterfall height={272} steps={wf} onClick={()=>push({kind:'explore',label:period.label,period,cf})}/>
        </div>
      </div>
    </ISection>
  );
}

/* ══ COMPARISON ENGINE ═════════════════════════════════════════════════════ */
function ISCompare({ ctx }){
  const { cur, prev, mode, period, cmpPeriod, push, cf } = ctx;
  const keys = IEg.metricList(mode);
  const color = window.IC.MODE_COLOR[mode];
  const [drill,setDrill]=isSt(null);
  if(!prev) return (
    <ISection title="Comparison Engine" anchor="i-compare" sub="Pick a comparison window in the control bar to unlock a full side-by-side breakdown of every metric.">
      <div className="i-card"><window.IC.Empty msg="No comparison period selected" h={120}/></div>
    </ISection>
  );
  return (
    <ISection title="Comparison Engine" anchor="i-compare"
      sub={period.label+' versus '+cmpPeriod.label+' — every metric, aligned date-for-date. Click any row to trace it back to its records.'}>
      <div className="i-card" style={{overflowX:'auto'}}>
        <table className="i-cmp">
          <thead><tr><th>Metric</th><th>{period.label}</th><th>{cmpPeriod.label}</th><th>Share</th><th>Change</th></tr></thead>
          <tbody>
            {keys.map(k=>{
              const meta=IEg.METRICS[k];
              const a=cur[k]||0, b=prev[k]||0;
              const top=Math.max(Math.abs(a),Math.abs(b))||1;
              const d = b!==0 ? (a-b)/Math.abs(b)*100 : (a>0?100:0);
              const better = meta.good==='down' ? d<0 : d>0;
              return (
                <tr key={k} className="kx-clickrow" tabIndex={0} onClick={()=>setDrill(k)}
                    onKeyDown={e=>{ if(e.key==='Enter'){ e.preventDefault(); setDrill(k); } }}
                    title={'Open '+meta.label+' detailed analysis'}>
                  <td>{meta.label}</td>
                  <td>{window.IC.fmt(a,meta.fmt)}</td>
                  <td style={{color:'var(--txt2)',fontWeight:600}}>{window.IC.fmt(b,meta.fmt)}</td>
                  <td><div className="i-cmp-bar"><i style={{width:(Math.abs(a)/top*100)+'%',background:color}}></i></div></td>
                  <td><ISDelta cur={a} prev={b} good={meta.good}/></td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>
      {drill && <ISKpiSheet ctx={ctx} mkey={drill} onClose={()=>setDrill(null)} onMetric={setDrill}/>}
    </ISection>
  );
}

/* ══ MATERIAL INTELLIGENCE ═════════════════════════════════════════════════ */
function ISMaterial({ ctx }){
  const { matRows, matPrev, mode, period, cf, push, setCF } = ctx;
  const color = window.IC.MODE_COLOR[mode];
  const growth = isMemo(()=>{
    const prevMap={}; (matPrev||[]).forEach(r=>prevMap[r.key]=r);
    return matRows.map(r=>{ const p=prevMap[r.key];
      const g = p && p.value>0 ? (r.value-p.value)/p.value*100 : (r.value>0 && matPrev ? 100 : null);
      return Object.assign({},r,{ growth:g, prevValue:p?p.value:0 }); })
      .filter(r=>r.growth!=null).sort((a,b)=>b.growth-a.growth);
  },[matRows,matPrev]);
  const total = matRows.reduce((s,r)=>s+r.value,0);
  const open = r => push({ kind:'explore', label:r.label, period, cf:Object.assign({},cf,{materialId:r.id}) });
  return (
    <ISection title="Material Intelligence" anchor="i-material"
      sub={'Which materials carry the period, which earn the most per ton, and which are shifting.'}
      right={<button className="i-ctl" onClick={()=>push({kind:'explore',label:'All materials',period,cf})}>Open explorer</button>}>
      <div className="i-grid i-g23">
        <div className="i-card hov">
          <div className="i-card-hd"><div><div className="i-card-t">{mode==='purchase'?'Procurement by material':'Revenue by material'}</div><div className="i-card-s">{matRows.length} materials · {window.IC.short(total)} total · click to cross-filter the whole page</div></div></div>
          <window.IC.Rank rows={matRows} valueKind="cur" limit={9} onClick={r=>setCF('materialId',r.id,r.label)}
            colorFor={(r,i)=>window.IC.PAL[i%window.IC.PAL.length]}
            right={r=>window.formatQuantity(r.qty)+' T'+(r.margin!=null?' · '+r.margin.toFixed(1)+'% margin':'')}/>
        </div>
        <div className="i-card hov">
          <div className="i-card-hd"><div><div className="i-card-t">Share of period</div><div className="i-card-s">Click a block to drill into it</div></div></div>
          <window.IC.Tree height={252} rows={matRows} valueKind="cur" onClick={open}/>
        </div>
      </div>
      {growth.length>1 && (
        <div className="i-grid i-g2" style={{marginTop:10}}>
          <div className="i-card hov">
            <div className="i-card-hd"><div><div className="i-card-t">Fastest growing</div><div className="i-card-s">Versus the comparison window</div></div></div>
            <window.IC.Rank rows={growth.slice(0,5).map(r=>({key:r.key,id:r.id,label:r.label,value:r.growth,sub:window.IC.short(r.prevValue)+' → '+window.IC.short(r.value)}))}
              valueKind="pct" colorFor={()=>'#16A34A'} onClick={open}/>
          </div>
          <div className="i-card hov">
            <div className="i-card-hd"><div><div className="i-card-t">Declining</div><div className="i-card-s">Needs attention on rate or demand</div></div></div>
            <window.IC.Rank rows={growth.slice(-5).reverse().map(r=>({key:r.key,id:r.id,label:r.label,value:r.growth,sub:window.IC.short(r.prevValue)+' → '+window.IC.short(r.value)}))}
              valueKind="pct" colorFor={()=>'#DC2626'} onClick={open}/>
          </div>
        </div>
      )}
    </ISection>
  );
}

/* ══ CUSTOMER / VENDOR INTELLIGENCE ════════════════════════════════════════ */
function ISParty({ ctx }){
  const { mode, custRows, vendRows, pats, period, cf, push, setCF, cur } = ctx;
  const isP = mode==='purchase';
  const rows = isP ? vendRows : custRows;
  const dimKey = isP ? 'vendorId' : 'customerId';
  const color = window.IC.MODE_COLOR[mode];
  const total = rows.reduce((s,r)=>s+r.value,0);
  const patMap={}; (pats||[]).forEach(p=>patMap[p.id]=p);
  const scored = isMemo(()=>rows.slice(0,10).map(r=>{
    const p=patMap[r.id];
    const share = total>0?r.value/total*100:0;
    const growth = p?Math.min(100,p.consistency*100):50;
    const risk = p ? (p.status==='dormant'?82:p.status==='overdue'?55:p.status==='due'?28:16) : 50;
    return Object.assign({},r,{ share, health:Math.round(Math.max(0,Math.min(100, 45+share*0.6+growth*0.32-risk*0.34))), pat:p, risk });
  }),[rows,total,pats]);
  const open = r => push({ kind:'explore', label:r.label, period, cf:Object.assign({},cf,{[dimKey]:r.id}) });
  return (
    <ISection title={isP?'Vendor Intelligence':'Customer Intelligence'} anchor="i-party"
      sub={isP?'Supplier concentration, reliability and rate behaviour across the period.':'Who drives the period, how healthy each account is, and where the concentration risk sits.'}>
      <div className="i-grid i-g23">
        <div className="i-card hov">
          <div className="i-card-hd"><div><div className="i-card-t">{isP?'Top vendors':'Top customers'}</div><div className="i-card-s">{rows.length} active · click to cross-filter the whole page</div></div></div>
          <window.IC.Rank rows={rows} valueKind="cur" limit={9} onClick={r=>setCF(dimKey,r.id,r.label)}
            colorFor={(r,i)=>window.IC.PAL[(i+2)%window.IC.PAL.length]}
            right={r=>(total>0?(r.value/total*100).toFixed(1):'0')+'% · '+r.count+' entr'+(r.count===1?'y':'ies')}/>
        </div>
        <div className="i-card hov" style={{display:'flex',flexDirection:'column',alignItems:'center',justifyContent:'center'}}>
          <div className="i-card-hd" style={{width:'100%'}}><div><div className="i-card-t">Concentration</div><div className="i-card-s">Top {Math.min(6,rows.length)} share · click a slice to drill in</div></div></div>
          <window.IC.Donut size={196} thickness={26} valueKind="cur"
            slices={rows.slice(0,6).map((r,i)=>({label:r.label,value:r.value,color:window.IC.PAL[(i+2)%window.IC.PAL.length],id:r.id}))}
            center={window.IC.short(total)} sub={isP?'PROCURED':'BILLED'}
            onClick={s=>push({kind:'explore',label:s.label,period,cf:Object.assign({},cf,{[dimKey]:s.id})})}/>
        </div>
      </div>
      {scored.length>0 && (
        <div className="i-card hov" style={{marginTop:10,overflowX:'auto'}}>
          <div className="i-card-hd"><div><div className="i-card-t">{isP?'Vendor':'Customer'} scorecard</div><div className="i-card-s">Health, growth consistency and risk derived from full transaction history</div></div></div>
          <table className="i-cmp">
            <thead><tr><th>{isP?'Vendor':'Customer'}</th><th>Value</th><th>Share</th><th>Avg cycle</th><th>Health</th><th>Risk</th></tr></thead>
            <tbody>
              {scored.map(r=>(
                <tr key={r.key} onClick={()=>r.pat?push({kind:'pattern',label:r.label,pat:r.pat}):open(r)}>
                  <td>{r.label}</td>
                  <td>{window.IC.cur(r.value)}</td>
                  <td>{r.share.toFixed(1)}%</td>
                  <td style={{color:'var(--txt2)',fontWeight:600}}>{r.pat?r.pat.medianGap.toFixed(0)+' d':'—'}</td>
                  <td><div className="i-cmp-bar"><i style={{width:r.health+'%',background:r.health>=65?'#16A34A':r.health>=45?'#F97316':'#DC2626'}}></i></div></td>
                  <td><span className={'i-delta '+(r.risk<30?'up':r.risk<60?'fl':'dn')}>{r.risk<30?'Low':r.risk<60?'Watch':'High'}</span></td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      )}
    </ISection>
  );
}

/* ══ BUYING PATTERN DETECTION ══════════════════════════════════════════════ */
function ISPatterns({ ctx }){
  const { pats, mode, push } = ctx;
  const list=(pats||[]).slice(0,6);
  const isP=mode==='purchase';
  if(!list.length) return null;
  return (
    <ISection title={isP?'Procurement Pattern Detection':'Buying Pattern Detection'} anchor="i-patterns"
      sub={'Learned automatically from transaction rhythm — no configuration. Each card explains exactly why the prediction was made.'}>
      <div className="i-grid i-g3">
        {list.map(p=>{
          const col = p.status==='dormant'?'#6B7068':p.status==='overdue'?'#DC2626':p.status==='due'?'#F97316':'#16A34A';
          const circ=2*Math.PI*22;
          return (
            <div className="i-pat" key={p.id} onClick={()=>push({kind:'pattern',label:p.label,pat:p})}>
              <div className="i-pat-hd">
                <div className="i-pat-n">{p.label}</div>
                <span className={'i-pat-st '+p.status}>{p.status}</span>
              </div>
              <div className="i-pat-ring">
                <div className="i-pat-conf">
                  <svg width="52" height="52" viewBox="0 0 52 52">
                    <circle cx="26" cy="26" r="22" fill="none" stroke="#F1EFEC" strokeWidth="5"/>
                    <circle cx="26" cy="26" r="22" fill="none" stroke={col} strokeWidth="5" strokeLinecap="round"
                      strokeDasharray={circ} strokeDashoffset={circ*(1-p.probability)} transform="rotate(-90 26 26)"
                      style={{transition:'stroke-dashoffset 1s cubic-bezier(.16,1,.3,1)'}}/>
                  </svg>
                  <b>{p.confidence}%</b>
                </div>
                <div className="i-pat-facts">
                  <div className="i-pat-f"><span>Next expected</span><b>{IEg.util.fmtD(p.nextDate)}</b></div>
                  <div className="i-pat-f"><span>Every</span><b>{p.medianGap.toFixed(0)} days</b></div>
                  <div className="i-pat-f"><span>Quantity</span><b>{window.formatQuantity(p.expectedQty)} T</b></div>
                  <div className="i-pat-f"><span>Value</span><b>{window.IC.short(p.expectedValue)}</b></div>
                </div>
              </div>
              <div className="i-pat-why">{p.reasons[2]}</div>
            </div>
          );
        })}
      </div>
    </ISection>
  );
}

/* ══ BILLING CYCLE PERFORMANCE ═════════════════════════════════════════════ */
function ISCycle({ ctx }){
  const { companyId, cf, mode, push } = ctx;
  const color = window.IC.MODE_COLOR[mode];
  const vk = mode==='purchase'?'purchaseValue':'revenue';
  const data = isMemo(()=>{
    const d=new Date(); const out=[];
    let y=d.getFullYear(), m=d.getMonth(), half=d.getDate()<=15?1:2;
    for(let i=0;i<8;i++){
      const c=IEg.Periods.cycle(y,m,half);
      out.unshift(c);
      if(half===2) half=1; else { half=2; m--; if(m<0){m=11;y--;} }
    }
    return out.map(c=>{ const mm=IEg.metrics(IEg.dataset(companyId,c,cf));
      return { label:(c.from.slice(8)==='01'?'H1 ':'H2 ')+IEg.MON[IEg.util.D(c.from).getMonth()], sub:c.label, period:c, v:mm[vk], p:mm.grossProfit, q:mm[mode==='purchase'?'qtyPurchased':'qtySold'] }; });
  },[companyId,JSON.stringify(cf),mode]);
  const last=data[data.length-1], prevC=data[data.length-2];
  const d = prevC && prevC.v>0 ? (last.v-prevC.v)/prevC.v*100 : 0;
  return (
    <ISection title="Billing Cycle Analysis" anchor="i-cycle"
      sub="The business runs on 15-day cycles — 1st to 15th and 16th to month end. This is that rhythm, cycle by cycle."
      right={<div className="i-ctl on" style={{cursor:'default'}}>Current cycle {d>=0?'+':''}{d.toFixed(1)}% vs previous</div>}>
      <div className="i-grid i-g23">
        <div className="i-card hov">
          <div className="i-card-hd"><div><div className="i-card-t">Last 8 billing cycles</div><div className="i-card-s">Click a cycle to open it</div></div></div>
          <window.IC.Bars height={250} yKind="cur" rows={data} keys={[{key:'v',label:mode==='purchase'?'Purchase Value':'Revenue',color},{key:'p',label:'Gross Profit',color:'#16A34A'}]}
            onClick={r=>push({kind:'explore',label:r.sub,period:r.period,cf})} subLabels/>
        </div>
        <div className="i-card hov">
          <div className="i-card-hd"><div><div className="i-card-t">Cycle quantity flow</div><div className="i-card-s">Tons moved per half-month</div></div></div>
          <window.IC.Area height={250} yKind="ton" labels={data.map(r=>r.label)} subLabels={data.map(r=>r.sub)}
            series={[{key:'q',label:'Quantity',color:'#7C3AED',values:data.map(r=>r.q)}]}
            onPointClick={i=>push({kind:'explore',label:data[i].sub,period:data[i].period,cf})}/>
        </div>
      </div>
    </ISection>
  );
}

/* ══ FORECASTING ═══════════════════════════════════════════════════════════ */
function ISForecast({ ctx }){
  const { companyId, cf, mode, push } = ctx;
  const [hz,setHz]=isSt('cycle');
  const color = window.IC.MODE_COLOR[mode];
  const HZ=[['week','Next Week','week',12,0],['cycle','Next Billing Cycle','cycle',14,24],['month','Next Month','month',18,12],['quarter','Next Quarter','quarter',10,4],['year','Next Year','year',5,0]];
  const cfg = HZ.find(h=>h[0]===hz);
  const data = isMemo(()=>{
    const grain=cfg[2], back=cfg[3], season=cfg[4];
    const t=IEg.util.today();
    let from;
    if(grain==='week') from=IEg.util.addDays(t,-7*back);
    else if(grain==='cycle') from=IEg.util.addMonths(t,-Math.ceil(back/2));
    else if(grain==='month') from=IEg.util.addMonths(t,-back);
    else if(grain==='quarter') from=IEg.util.addMonths(t,-3*back);
    else from=IEg.util.addMonths(t,-12*back);
    const pd=IEg.P('custom',from,t,'history','');
    const s=IEg.series(companyId,pd,cf,grain);
    const vk = mode==='purchase'?'purchaseValue':'revenue';
    const vals=s.points.map(p=>p.m[vk]);
    const qty=s.points.map(p=>p.m[mode==='purchase'?'qtyPurchased':'qtySold']);
    const prof=s.points.map(p=>p.m.grossProfit);
    return {
      s, labels:s.points.map(p=>p.label),
      rev:IEg.forecast(vals,3,{season}),
      qty:IEg.forecast(qty,3,{season}),
      prof:IEg.forecast(prof,3,{season}),
    };
  },[companyId,JSON.stringify(cf),mode,hz]);
  const fc=data.rev;
  const n=data.labels.length;
  const labels=data.labels.concat(fc.points.map((p,i)=>'+'+(i+1)));
  const actual=data.s.points.map(p=>p.m[mode==='purchase'?'purchaseValue':'revenue']).concat(fc.points.map(()=>0));
  const proj=data.s.points.map((p,i)=>i===n-1?p.m[mode==='purchase'?'purchaseValue':'revenue']:0).concat(fc.points.map(p=>p.value));
  const band=data.s.points.map(()=>0).concat(fc.points.map(p=>p.hi));
  const M = mode==='purchase' ? [['Forecast Purchase Value',fc,'cur'],['Forecast Quantity',data.qty,'ton'],['Forecast Margin Impact',data.prof,'cur']]
                              : [['Forecast Revenue',fc,'cur'],['Forecast Quantity',data.qty,'ton'],['Forecast Gross Profit',data.prof,'cur']];
  return (
    <ISection title="AI Forecasting Engine" anchor="i-forecast"
      sub={'Genuine in-browser statistics — trend regression, weighted momentum, seasonal indexing and residual confidence bands. Every figure is explained.'}
      right={<div style={{display:'flex',gap:5,flexWrap:'wrap'}}>{HZ.map(h=>(
        <button key={h[0]} className={'i-ctl sm'+(hz===h[0]?' on':'')} onClick={()=>setHz(h[0])}>{h[1]}</button>))}</div>}>
      <div className="i-grid i-g23">
        <div className="i-card hov">
          <div className="i-card-hd">
            <div><div className="i-card-t">{cfg[1]} projection</div><div className="i-card-s">{fc.method}</div></div>
            <div className="i-delta up" style={{background:'#F5F3FF',color:'#6D28D9'}}>{fc.confidence}% confidence</div>
          </div>
          <window.IC.Area height={264} yKind="cur" labels={labels} series={[
            {key:'b',label:'Upper band',color:'#D6D2CD',dashed:true,values:band},
            {key:'a',label:'Actual',color,values:actual},
            {key:'f',label:'Forecast',color:'#7C3AED',dashed:true,values:proj},
          ]} onPointClick={()=>push({kind:'forecast',label:cfg[1]+' forecast',fc,labels:data.labels})}/>
          <div style={{display:'flex',gap:8,flexWrap:'wrap',marginTop:11}}>
            {M.map((x,i)=>(
              <div key={i} style={{flex:'1 1 150px',padding:'9px 11px',borderRadius:11,background:'#FCFBFA',border:'1px solid var(--bdr)'}}>
                <div style={{fontSize:9,fontWeight:800,letterSpacing:'.07em',textTransform:'uppercase',color:'var(--txt3)'}}>{x[0]}</div>
                <div style={{fontSize:15,fontWeight:800,letterSpacing:'-.03em',marginTop:3}}><window.IC.Num value={x[1].points[0]?x[1].points[0].value:0} kind={x[2]}/></div>
                <div style={{fontSize:10,color:x[1].growthPct>=0?'#15803D':'#B91C1C',fontWeight:700,marginTop:2}}>{x[1].growthPct>=0?'+':''}{x[1].growthPct.toFixed(1)}% vs last</div>
              </div>
            ))}
          </div>
        </div>
        <div className="i-card hov">
          <div className="i-card-hd"><div><div className="i-card-t">Why this forecast</div><div className="i-card-s">Plain-language reasoning behind every number</div></div></div>
          <ul className="i-ins-r" style={{marginTop:0,paddingTop:0,borderTop:0}}>
            {fc.reasons.map((r,i)=><li key={i} style={{'--ic':'#7C3AED',fontSize:11}}>{r}</li>)}
          </ul>
          <table className="i-cmp" style={{marginTop:12}}>
            <thead><tr><th>Ahead</th><th>Forecast</th><th>Low</th><th>High</th></tr></thead>
            <tbody>{fc.points.map((p,i)=>(
              <tr key={i} onClick={()=>push({kind:'forecast',label:cfg[1]+' forecast',fc,labels:data.labels})}>
                <td>+{i+1} {cfg[2]}</td><td>{window.IC.short(p.value)}</td>
                <td style={{color:'var(--txt2)',fontWeight:600}}>{window.IC.short(p.lo)}</td>
                <td style={{color:'var(--txt2)',fontWeight:600}}>{window.IC.short(p.hi)}</td>
              </tr>))}
            </tbody>
          </table>
        </div>
      </div>
    </ISection>
  );
}

/* ══ SEASONAL INTELLIGENCE ═════════════════════════════════════════════════ */
function ISSeasonal({ ctx }){
  const { seas, companyId, cf, mode, push } = ctx;
  const color = window.IC.MODE_COLOR[mode];
  const heat = isMemo(()=>{
    const t=IEg.util.today(); const cells=[];
    const start=IEg.util.weekStart(IEg.util.addDays(t,-181));
    const all = mode==='purchase'?(Store.all('purchases',companyId)||[]):(Store.all('salesOrders',companyId)||[]);
    const byD={};
    all.forEach(r=>{ if(!IEg.matchCF(r,cf,mode==='purchase'?'purchases':'sales')) return;
      const d=String(r.date||'').slice(0,10); if(!d) return;
      if(!byD[d]) byD[d]={v:0,c:0}; byD[d].v+=window.gAmt(r); byD[d].c++; });
    for(let s=start; s<=t; s=IEg.util.addDays(s,1)){
      const x=byD[s]||{v:0,c:0};
      cells.push({ date:s, label:IEg.util.fmtD(s), value:x.v, count:x.c });
    }
    return cells;
  },[companyId,JSON.stringify(cf),mode]);
  if(!seas.hasData) return null;
  return (
    <ISection title="Seasonal Intelligence" anchor="i-seasonal"
      sub={'Recurring yearly behaviour learned from '+seas.years+' year'+(seas.years===1?'':'s')+' of history in this company — monsoon, festival, construction season and financial-year closing.'}
      right={<button className="i-ctl" onClick={()=>push({kind:'season',label:'Seasonal detail',seas})}>Full breakdown</button>}>
      <div className="i-grid i-g23">
        <div className="i-card hov">
          <div className="i-card-hd"><div><div className="i-card-t">Daily activity — last 26 weeks</div><div className="i-card-s">Click a day to open it</div></div></div>
          <window.IC.Heat cells={heat} valueKind="cur" weeks={Math.ceil(heat.length/7)}
            onClick={c=>push({kind:'explore',label:IEg.util.fmtD(c.date),period:IEg.Periods.day(c.date),cf})}/>
        </div>
        <div className="i-card hov">
          <div className="i-card-hd"><div><div className="i-card-t">Seasonal windows</div><div className="i-card-s">Index versus the average month</div></div></div>
          <window.IC.Rank rows={seas.seasons.map(s=>({key:s.key,label:s.label,value:s.deltaPct,sub:s.note}))} valueKind="pct"
            max={Math.max.apply(null,seas.seasons.map(s=>Math.abs(s.deltaPct)).concat([10]))}
            colorFor={r=>r.value>=0?'#16A34A':'#DC2626'}/>
        </div>
      </div>
      <div className="i-card hov" style={{marginTop:10}}>
        <div className="i-card-hd"><div><div className="i-card-t">Month-by-month seasonality index</div><div className="i-card-s">Every year of history collapsed onto one calendar year</div></div></div>
        <window.IC.Bars height={210} yKind="cur" rows={seas.index.map(x=>({label:x.label,v:x.value}))}
          keys={[{key:'v',label:'Historic total',color}]}
          onClick={r=>{ const mi=IEg.MON.indexOf(r.label); if(mi>=0) push({kind:'explore',label:r.label+' '+new Date().getFullYear(),period:IEg.Periods.month(new Date().getFullYear(),mi),cf}); }}/>
      </div>
    </ISection>
  );
}

/* ══ AI INSIGHTS & RECOMMENDATIONS ═════════════════════════════════════════ */
function ISInsights({ ctx }){
  const { ins, push } = ctx;
  const KIND={ risk:{c:'#DC2626',l:'Risk'}, opportunity:{c:'#16A34A',l:'Opportunity'}, action:{c:'#F97316',l:'Recommended action'}, info:{c:'#2563EB',l:'Signal'} };
  const [filter,setFilter]=isSt('all');
  const list = filter==='all'?ins:ins.filter(i=>i.kind===filter);
  if(!ins.length) return null;
  return (
    <ISection title="AI Insights & Recommendations" anchor="i-insights"
      sub="Generated live from the current selection. Every card states its reasoning and opens the underlying records."
      right={<div style={{display:'flex',gap:5,flexWrap:'wrap'}}>
        {[['all','All ('+ins.length+')'],['risk','Risks'],['opportunity','Opportunities'],['action','Actions']].map(f=>(
          <button key={f[0]} className={'i-ctl sm'+(filter===f[0]?' on':'')} onClick={()=>setFilter(f[0])}>{f[1]}</button>))}
      </div>}>
      <div className="i-grid i-g3">
        {list.map((x,i)=>{
          const k=KIND[x.kind]||KIND.info;
          return (
            <div className="i-ins" key={x.id} style={{'--ic':k.c,animation:'iRow .55s '+(i*48)+'ms cubic-bezier(.16,1,.3,1) both'}}
                 onClick={()=>push({kind:'insight',label:x.title.length>34?x.title.slice(0,33)+'…':x.title,ins:x})}>
              <span className="i-ins-k">{k.l}</span>
              <div className="i-ins-t">{x.title}</div>
              <div className="i-ins-d">{x.detail}</div>
              {x.reasons && x.reasons.length>0 && (
                <ul className="i-ins-r">{x.reasons.slice(0,2).map((r,j)=><li key={j}>{r}</li>)}</ul>
              )}
              <div className="i-ins-more">Open the evidence →</div>
            </div>
          );
        })}
      </div>
    </ISection>
  );
}

/* ══ HEALTH SCORE ══════════════════════════════════════════════════════════ */
function ISHealth({ ctx }){
  const { health, push, cur, prev, mode } = ctx;
  return (
    <ISection title="Business Health Score" anchor="i-health"
      sub="One number, eight weighted drivers, all live. Tap any driver to see exactly what feeds it."
      right={<button className="i-ctl" onClick={()=>push({kind:'health',label:'Health detail',health})}>Full diagnostic</button>}>
      <div className="i-grid i-g32">
        <div className="i-card hov" style={{display:'flex',flexDirection:'column',alignItems:'center',justifyContent:'center',gap:6,cursor:'pointer'}}
             onClick={()=>push({kind:'health',label:'Health detail',health})}>
          <window.IC.Gauge value={health.score} size={214} label={health.grade.toUpperCase()} sub={'Weighted across '+health.parts.length+' drivers'}/>
          <div style={{fontSize:10.5,color:'var(--txt2)',textAlign:'center',lineHeight:1.5,maxWidth:260}}>
            {health.growth>=0?'Growth is positive at +':'Growth is negative at '}{health.growth.toFixed(1)}% with a {cur.margin.toFixed(1)}% gross margin.
          </div>
        </div>
        <div className="i-card hov">
          <div className="i-card-hd"><div><div className="i-card-t">Driver breakdown</div><div className="i-card-s">Each driver scored 0–100 and weighted into the headline figure</div></div></div>
          <div className="i-hp">
            {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 className="i-hp-w">{(p.weight*100).toFixed(0)}%</span></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>=50?'#F97316':'#DC2626'}}></div></div>
                <div className="i-hp-d">{p.detail}</div>
              </div>
            ))}
          </div>
        </div>
      </div>
    </ISection>
  );
}

/* ══ OPERATIONAL INTELLIGENCE ══════════════════════════════════════════════ */
function ISOps({ ctx }){
  const { cur, prev, crusherRows, mode, period, cf, push, ser } = ctx;
  const color = window.IC.MODE_COLOR[mode];
  const funnel = mode==='purchase'
    ? [{label:'Purchase entries',value:cur.pos},{label:'Delivered',value:ctx.ds.purchases.filter(p=>p.status==='Delivered').length},{label:'Diesel linked',value:ctx.ds.purchases.filter(p=>IEg.num(p.dieselQty)>0).length}]
    : [{label:'Tons purchased',value:cur.qtyPurchased},{label:'Tons sold',value:cur.qtySold},{label:'Tons billed',value:cur.qtySold}];
  const ops=[
    ['Trips completed', cur.trips, 'int'],
    ['Avg load per trip', cur.avgLoad, 'ton'],
    ['Transport cost', cur.transportCost, 'cur'],
    ['Diesel paid', cur.dieselCost, 'cur'],
    ['Diesel recovered', cur.recovery, 'cur'],
    ['Diesel margin earned', cur.dieselMargin, 'cur'],
    ['Sell-through', cur.sellThrough, 'pct'],
    ['Internal transfers', cur.transfersQty, 'ton'],
  ];
  return (
    <ISection title="Operational Intelligence" anchor="i-ops"
      sub="Fleet, crusher and diesel behaviour behind the financial numbers.">
      <div className="i-grid i-g23">
        <div className="i-card hov">
          <div className="i-card-hd"><div><div className="i-card-t">Crusher / site performance</div><div className="i-card-s">Where volume actually originates</div></div></div>
          {crusherRows.length
            ? <window.IC.Rank rows={crusherRows} valueKind="cur" limit={8}
                colorFor={(r,i)=>window.IC.PAL[(i+5)%window.IC.PAL.length]}
                right={r=>window.formatQuantity(r.qty)+' T'}
                onClick={r=>push({kind:'explore',label:r.label,period,cf:Object.assign({},cf,{crusherSite:r.id})})}/>
            : <window.IC.Empty msg="No crusher tagged on records in this period"/>}
        </div>
        <div className="i-card hov">
          <div className="i-card-hd"><div><div className="i-card-t">Operational metrics</div><div className="i-card-s">Live against the current selection</div></div></div>
          <div style={{display:'grid',gridTemplateColumns:'repeat(auto-fit,minmax(132px,1fr))',gap:8}}>
            {ops.map((o,i)=>(
              <div key={i} style={{padding:'9px 11px',borderRadius:11,background:'#FCFBFA',border:'1px solid var(--bdr)'}}>
                <div style={{fontSize:9,fontWeight:800,letterSpacing:'.07em',textTransform:'uppercase',color:'var(--txt3)'}}>{o[0]}</div>
                <div style={{fontSize:14.5,fontWeight:800,letterSpacing:'-.028em',marginTop:3}}><window.IC.Num value={o[1]} kind={o[2]}/></div>
                {prev && <div style={{marginTop:3}}><ISDelta cur={o[1]} prev={prev[['trips','avgLoad','transportCost','dieselCost','recovery','dieselMargin','sellThrough','transfersQty'][i]]} good={i>=2&&i<=3?'down':'up'}/></div>}
              </div>
            ))}
          </div>
          <div style={{marginTop:12}}>
            <div className="i-card-t" style={{marginBottom:8,fontSize:11}}>{mode==='purchase'?'Procurement funnel':'Material flow funnel'}</div>
            <window.IC.Funnel rows={funnel} valueKind={mode==='purchase'?'int':'ton'}/>
          </div>
        </div>
      </div>
    </ISection>
  );
}

Object.assign(window, { ISection, ISKpis, ISKpiSheet, ISPerformance, ISCompare, ISMaterial, ISParty, ISPatterns, ISCycle, ISForecast, ISSeasonal, ISInsights, ISHealth, ISOps, ISDelta, useInView });
