/* OM Group ERP — Analytics & Intelligence Center (flagship module)
   Live analytics layer over the ERP. Holds no data of its own: every render
   re-derives from Store through IntelEngine, and Store.on() re-renders the
   whole module, so any sales/purchase/diesel/transfer edit anywhere in the
   ERP is reflected here immediately.                                       */
const { useState: icpSt, useEffect: icpEf, useMemo: icpMemo, useRef: icpRef, useContext: icpCtx, useLayoutEffect: icpLay } = React;
const IEc = window.IntelEngine;

/* ── segmented Sales / Purchase switch ─────────────────────────────────── */
function IModeSwitch({ mode, onChange }){
  const wrap=icpRef(null); const a=icpRef(null); const b=icpRef(null);
  const [pill,setPill]=icpSt({left:3,width:0});
  icpLay(()=>{
    const el = mode==='purchase'?b.current:a.current;
    if(!el||!wrap.current) return;
    const w=wrap.current.getBoundingClientRect(), e=el.getBoundingClientRect();
    setPill({ left:e.left-w.left, width:e.width });
  },[mode]);
  icpEf(()=>{
    const on=()=>{ const el=mode==='purchase'?b.current:a.current; if(!el||!wrap.current) return;
      const w=wrap.current.getBoundingClientRect(), e=el.getBoundingClientRect(); setPill({left:e.left-w.left,width:e.width}); };
    window.addEventListener('resize',on); return ()=>window.removeEventListener('resize',on);
  },[mode]);
  return (
    <div className="i-seg" ref={wrap} role="tablist">
      <div className="i-seg-pill" style={{transform:'translateX('+pill.left+'px)',width:pill.width}}></div>
      <button ref={a} className={mode==='sales'?'on':''} onClick={()=>onChange('sales')} role="tab" aria-selected={mode==='sales'}>{window.OMIcon ? <window.OMIcon name="sales" size={13}/> : <i></i>}Sales Analytics</button>
      <button ref={b} className={mode==='purchase'?'on':''} onClick={()=>onChange('purchase')} role="tab" aria-selected={mode==='purchase'}>{window.OMIcon ? <window.OMIcon name="purchase" size={13}/> : <i></i>}Purchase Analytics</button>
    </div>
  );
}

/* ── period picker: enterprise-grade time explorer ───────────────────────
   11 tabs cover every horizon an ERP with years of history needs. Years are
   never hardcoded — `years` is the live set pulled from every record in
   Store (IEc.allYears), so the picker grows automatically as data grows. */
const IP_TABS=[['quick','Quick'],['cycle','Billing Cycle'],['month','Month'],['quarter','Quarter'],['half','Half Year'],['fy','Financial Year'],['calendar','Calendar Year'],['year','Year'],['multi','Multi-Year'],['rolling','Rolling Period'],['custom','Custom']];
function IPeriodPickerBody({ period, onPick, years, favorites, recent }){
  const [tab,setTab]=icpSt('quick');
  const nowY=new Date().getFullYear();
  const [y,setY]=icpSt(IEc.util.D(period.from).getFullYear()||nowY);
  const [cf,setCf]=icpSt(period.from); const [ct,setCt]=icpSt(period.to);
  const P=IEc.Periods;
  const curQ=Math.floor(new Date().getMonth()/3)+1;
  const prevM=IEc.util.D(IEc.util.addMonths(IEc.util.today(),-1));
  const isSame=q=>q.from===period.from&&q.to===period.to;
  const quick=[
    ['Today',P.today()],['Yesterday',P.yesterday()],
    ['Last 7 days',P.rolling(7)],['Last 15 days',P.rolling(15)],['Last 30 days',P.rolling(30)],['Last 45 days',P.rolling(45)],
    ['Last 60 days',P.rolling(60)],['Last 90 days',P.rolling(90)],['Last 180 days',P.rolling(180)],['Last 365 days',P.rolling(365)],
    ['Current week',P.week(IEc.util.today())],['Previous week',P.week(IEc.util.addDays(IEc.util.today(),-7))],
    ['Current billing cycle',P.currentCycle()],['Previous billing cycle',P.prevCycle()],
    ['Current month',P.thisMonth()],['Previous month',P.month(prevM.getFullYear(),prevM.getMonth())],
    ['Current quarter',P.quarter(nowY,curQ)],['Previous quarter',curQ===1?P.quarter(nowY-1,4):P.quarter(nowY,curQ-1)],
    ['Current financial year',P.fy(IEc.util.fyOf(IEc.util.today()))],['Previous financial year',P.fy(IEc.util.fyOf(IEc.util.today())-1)],
    ['Year to date',P.yearToDate()],['Month to date',P.monthToDate()],['Quarter to date',P.quarterToDate()],['Billing cycle to date',P.cycleToDate()],
  ];
  const yearsAsc = (years&&years.length ? years.slice() : [nowY-2,nowY-1,nowY]);
  if(yearsAsc[yearsAsc.length-1]<nowY+1) yearsAsc.push(nowY+1);
  const yearList = yearsAsc.slice().reverse();
  const [my1,setMy1]=icpSt(yearsAsc[0]); const [my2,setMy2]=icpSt(yearsAsc[yearsAsc.length-1]);
  return (
    <>
      <div className="i-pop-hd" style={{display:'flex',gap:4,flexWrap:'wrap',padding:'8px 8px'}}>
        {IP_TABS.map(t=>(
          <button key={t[0]} className={'i-ctl sm'+(tab===t[0]?' on':'')} style={{textTransform:'none',letterSpacing:0}} onClick={()=>setTab(t[0])}>{t[1]}</button>
        ))}
      </div>
      <div className="i-pop-body">
        {tab==='quick' && quick.map((q,i)=>(
          <div key={i} className={'i-opt'+(isSame(q[1])?' on':'')} onClick={()=>onPick(q[1])}>
            <span>{q[0]}</span><em>{q[1].sub||q[1].label}</em>
          </div>
        ))}
        {tab==='cycle' && (<>
          <div className="i-pop-grp">Quick</div>
          <div className="i-grid2">
            <button className={isSame(P.currentCycle())?'on':''} onClick={()=>onPick(P.currentCycle())}>Current Cycle</button>
            <button onClick={()=>onPick(P.prevCycle())}>Previous Cycle</button>
            <button onClick={()=>onPick(P.nextCycle())}>Next Cycle (Forecast)</button>
            <button onClick={()=>onPick(P.cycleToDate())}>Cycle to Date</button>
          </div>
          <div className="i-pop-grp">Year</div>
          <div className="i-grid3">{yearList.map(yy=><button key={yy} className={y===yy?'on':''} onClick={()=>setY(yy)}>{yy}</button>)}</div>
          <div className="i-pop-grp">First half — 1st to 15th</div>
          <div className="i-grid2">{IEc.MON.map((m,i)=><button key={i} className={isSame(P.cycle(y,i,1))?'on':''} onClick={()=>onPick(P.cycle(y,i,1))}>{m}</button>)}</div>
          <div className="i-pop-grp">Second half — 16th to month end</div>
          <div className="i-grid2">{IEc.MON.map((m,i)=><button key={i} className={isSame(P.cycle(y,i,2))?'on':''} onClick={()=>onPick(P.cycle(y,i,2))}>{m}</button>)}</div>
        </>)}
        {tab==='month' && (<>
          <div className="i-pop-grp">Year</div>
          <div className="i-grid3">{yearList.map(yy=><button key={yy} className={y===yy?'on':''} onClick={()=>setY(yy)}>{yy}</button>)}</div>
          <div className="i-pop-grp">Pick a month</div>
          <div className="i-grid2">{IEc.MON.map((m,i)=><button key={i} className={period.kind==='month'&&IEc.util.D(period.from).getMonth()===i&&IEc.util.D(period.from).getFullYear()===y?'on':''} onClick={()=>onPick(P.month(y,i))}>{m}</button>)}</div>
          <div className="i-pop-grp">Weeks inside a month</div>
          <div className="i-grid3">{[1,2,3,4,5].map(n=><button key={n} onClick={()=>onPick(P.weekOfMonth(y,IEc.util.D(period.from).getMonth(),n))}>W{n}</button>)}</div>
        </>)}
        {tab==='quarter' && (<>
          <div className="i-pop-grp">Quick</div>
          <div className="i-grid2">
            <button className={isSame(P.quarter(nowY,curQ))?'on':''} onClick={()=>onPick(P.quarter(nowY,curQ))}>Current Quarter</button>
            <button onClick={()=>onPick(curQ===1?P.quarter(nowY-1,4):P.quarter(nowY,curQ-1))}>Previous Quarter</button>
            <button onClick={()=>onPick(P.quarter(nowY-1,curQ))}>Same Quarter Last Year</button>
            <button onClick={()=>onPick(P.rollingMonths(3,'Rolling Quarter'))}>Rolling Quarter</button>
          </div>
          <div className="i-pop-grp">Year</div>
          <div className="i-grid3">{yearList.map(yy=><button key={yy} className={y===yy?'on':''} onClick={()=>setY(yy)}>{yy}</button>)}</div>
          <div className="i-pop-grp">Quarter</div>
          <div className="i-grid2">{[1,2,3,4].map(q=><button key={q} className={period.kind==='quarter'&&IEc.util.D(period.from).getFullYear()===y&&Math.floor(IEc.util.D(period.from).getMonth()/3)+1===q?'on':''} onClick={()=>onPick(P.quarter(y,q))}>Q{q}</button>)}</div>
        </>)}
        {tab==='half' && (<>
          <div className="i-pop-grp">Quick</div>
          <div className="i-grid2">
            <button className={isSame(P.currentHalf())?'on':''} onClick={()=>onPick(P.currentHalf())}>Current Half</button>
            <button onClick={()=>onPick(P.prevHalf())}>Previous Half</button>
          </div>
          <div className="i-pop-grp">Year</div>
          <div className="i-grid3">{yearList.map(yy=><button key={yy} className={y===yy?'on':''} onClick={()=>setY(yy)}>{yy}</button>)}</div>
          <div className="i-pop-grp">Half</div>
          <div className="i-grid2">
            <button className={isSame(P.half(y,1))?'on':''} onClick={()=>onPick(P.half(y,1))}>H1 · Jan–Jun</button>
            <button className={isSame(P.half(y,2))?'on':''} onClick={()=>onPick(P.half(y,2))}>H2 · Jul–Dec</button>
          </div>
        </>)}
        {tab==='fy' && (<>
          <div className="i-pop-grp">Quick</div>
          <div className="i-grid2">
            <button className={isSame(P.fy(IEc.util.fyOf(IEc.util.today())))?'on':''} onClick={()=>onPick(P.fy(IEc.util.fyOf(IEc.util.today())))}>Current FY</button>
            <button onClick={()=>onPick(P.fy(IEc.util.fyOf(IEc.util.today())-1))}>Previous FY</button>
          </div>
          <div className="i-pop-grp">Every financial year</div>
          <div className="i-yr-list">{yearList.map(yy=>(
            <div key={yy} className={'i-opt'+(period.kind==='fy'&&IEc.util.D(period.from).getFullYear()===yy?' on':'')} onClick={()=>onPick(P.fy(yy))}>
              <span>FY {yy}–{String(yy+1).slice(2)}</span><em>Apr {yy} – Mar {yy+1}</em>
            </div>
          ))}</div>
        </>)}
        {tab==='calendar' && (<>
          <div className="i-pop-grp">Calendar year</div>
          <div className="i-grid3">{yearList.map(yy=><button key={yy} className={period.kind==='year'&&IEc.util.D(period.from).getFullYear()===yy?'on':''} onClick={()=>onPick(P.year(yy))}>{yy}</button>)}</div>
        </>)}
        {tab==='year' && (<>
          <div className="i-pop-grp">Every year in this ERP ({yearList.length})</div>
          <div className="i-yr-list">{yearList.map(yy=>(
            <div key={yy} className={'i-opt'+(period.kind==='year'&&IEc.util.D(period.from).getFullYear()===yy?' on':'')} onClick={()=>onPick(P.year(yy))}>
              <span>{yy}</span><em>{yy===nowY?'Current year':yy>nowY?'Future — no data yet':'Calendar year'}</em>
            </div>
          ))}</div>
        </>)}
        {tab==='multi' && (<>
          <div className="i-pop-grp">Quick spans</div>
          <div className="i-grid2">
            {[2,3,5,10].map(n=><button key={n} onClick={()=>onPick(P.multiYear(Math.max(yearsAsc[0],nowY-n+1),nowY))}>{n} Years</button>)}
          </div>
          <div className="i-pop-grp">Custom range</div>
          <div style={{display:'flex',gap:6,padding:'4px 10px 10px',alignItems:'center',flexWrap:'wrap'}}>
            <select className="inp" value={my1} onChange={e=>setMy1(+e.target.value)} style={{flex:1,minWidth:80}}>{yearsAsc.map(yy=><option key={yy} value={yy}>{yy}</option>)}</select>
            <span style={{fontSize:11,color:'var(--iInk3)'}}>to</span>
            <select className="inp" value={my2} onChange={e=>setMy2(+e.target.value)} style={{flex:1,minWidth:80}}>{yearsAsc.map(yy=><option key={yy} value={yy}>{yy}</option>)}</select>
            <button className="btn btn-or" onClick={()=>onPick(P.multiYear(my1,my2))}>Apply</button>
          </div>
          <div className="i-opt" style={{margin:'0 6px 8px'}} onClick={()=>onPick(P.multiYear(yearsAsc[0],yearsAsc[yearsAsc.length-1]))}>
            <span>Entire history</span><em>{yearsAsc[0]}–{yearsAsc[yearsAsc.length-1]}</em>
          </div>
        </>)}
        {tab==='rolling' && (<>
          <div className="i-pop-grp">Rolling window (ends today)</div>
          <div className="i-grid2">
            {[3,6,12,24,36].map(n=><button key={n} className={isSame(P.rollingMonths(n,'Rolling '+n+' Months'))?'on':''} onClick={()=>onPick(P.rollingMonths(n,'Rolling '+n+' Months'))}>{n} Months</button>)}
            <button onClick={()=>onPick(P.rollingCycles(2,'Rolling Billing Cycle'))}>Billing Cycle</button>
            <button onClick={()=>onPick(P.rollingMonths(3,'Rolling Quarter'))}>Quarter</button>
            <button onClick={()=>onPick(P.rollingMonths(12,'Rolling Year'))}>Year</button>
          </div>
        </>)}
        {tab==='custom' && (<>
          <div className="i-pop-grp">Any two dates</div>
          <div style={{padding:'4px 10px 10px',display:'grid',gap:7}}>
            <label style={{fontSize:10,fontWeight:700,color:'var(--iInk2)'}}>From
              <input className="inp" type="date" value={cf} onChange={e=>setCf(e.target.value)} style={{marginTop:3}}/></label>
            <label style={{fontSize:10,fontWeight:700,color:'var(--iInk2)'}}>To
              <input className="inp" type="date" value={ct} onChange={e=>setCt(e.target.value)} style={{marginTop:3}}/></label>
            <button className="btn btn-or" onClick={()=>{ if(cf&&ct) onPick(P.custom(cf>ct?ct:cf, cf>ct?cf:ct)); }}>Apply range</button>
          </div>
          {favorites&&favorites.length>0 && (<>
            <div className="i-pop-grp">Favourite periods</div>
            {favorites.map((f,i)=><div key={i} className={'i-opt'+(isSame(f)?' on':'')} onClick={()=>onPick(f)}><span>★ {f.label}</span><em>{f.sub}</em></div>)}
          </>)}
          {recent&&recent.length>0 && (<>
            <div className="i-pop-grp">Recent selections</div>
            {recent.map((f,i)=><div key={i} className={'i-opt'+(isSame(f)?' on':'')} onClick={()=>onPick(f)}><span>{f.label}</span><em>{f.sub}</em></div>)}
          </>)}
        </>)}
      </div>
    </>
  );
}
function IPeriodPicker(props){
  return <div className="i-pop" style={{width:'min(460px,92vw)'}}><IPeriodPickerBody {...props}/></div>;
}

/* ── global search ─────────────────────────────────────────────────────── */
const ISR_COLOR={ material:'#F97316', customer:'#7C3AED', vendor:'#2563EB', crusher:'#0891B2', plant:'#0D9488', transporter:'#4F46E5', vehicle:'#CA8A04', salesOrder:'#F97316', purchaseOrder:'#2563EB', month:'#16A34A', quarter:'#16A34A', year:'#16A34A', metric:'#DB2777' };
function ISearchResults({ q, index, onPick }){
  const list=icpMemo(()=>{
    const s=q.trim().toLowerCase(); if(!s) return [];
    return index.filter(x=>x.label.toLowerCase().indexOf(s)>=0).slice(0,9);
  },[q,index]);
  if(!q.trim()) return null;
  return (
    <div className="i-pop" style={{width:'min(380px,92vw)'}}>
      <div className="i-pop-hd">{list.length?list.length+' match'+(list.length===1?'':'es'):'No match'}</div>
      <div className="i-sr">
        {list.map((x,i)=>(
          <div className="i-sr-it" key={i} onClick={()=>onPick(x)}>
            <span className="i-sr-k" style={{background:ISR_COLOR[x.type]||'#6B7068'}}>{x.type[0].toUpperCase()}</span>
            <span className="i-sr-l">{x.label}</span>
            <span className="i-sr-s">{x.sub}</span>
          </div>
        ))}
      </div>
    </div>
  );
}

/* ── skeleton ──────────────────────────────────────────────────────────── */
function IBoot(){
  return (
    <div style={{marginTop:16}}>
      <div className="i-kpis">{[0,1,2,3,4,5].map(i=><div key={i} className="i-sk" style={{height:88,borderRadius:15,animationDelay:(i*90)+'ms'}}></div>)}</div>
      <div className="i-grid i-g23" style={{marginTop:14}}>
        <div className="i-sk" style={{height:330,borderRadius:16}}></div>
        <div className="i-sk" style={{height:330,borderRadius:16,animationDelay:'140ms'}}></div>
      </div>
      <div className="i-grid i-g3" style={{marginTop:14}}>{[0,1,2].map(i=><div key={i} className="i-sk" style={{height:150,borderRadius:15,animationDelay:(i*110)+'ms'}}></div>)}</div>
    </div>
  );
}

/* Opening period: this month if it already has activity, otherwise the month
   of the most recent transaction — the module never opens on an empty screen. */
function smartPeriod(companyId){
  const t=IEc.util.today(), mon=t.slice(0,7);
  const S=(Store.all('salesOrders',companyId)||[]), P=(Store.all('purchases',companyId)||[]);
  const has = S.some(r=>String(r.date||'').slice(0,7)===mon) || P.some(r=>String(r.date||'').slice(0,7)===mon);
  if(has) return IEc.Periods.thisMonth();
  let latest='';
  S.concat(P).forEach(r=>{ const d=String(r.date||'').slice(0,10); if(d&&d>latest&&d<=t) latest=d; });
  if(!latest) return IEc.Periods.thisMonth();
  const d=IEc.util.D(latest);
  return IEc.Periods.month(d.getFullYear(), d.getMonth());
}

/* ── page ──────────────────────────────────────────────────────────────── */
function IntelCenterPage(){
  const app = icpCtx(window.AppCtx);
  const companyId = app.companyId;
  const [ver,setVer]=icpSt(0);
  /* One workspace per ERP function. 'sales' and 'purchase' render the original
     Intelligence Center sections; every other id is a declared domain in
     window.IntelDomains and renders through the universal workspace. */
  const DOMS = window.IntelDomains;
  const [domain,setDomain]=icpSt(()=>{ const s=localStorage.getItem('omIntelDomain')||localStorage.getItem('omIntelMode')||'sales';
    /* the retired Recovery & Collection workspace resolves to Financial Intelligence, which now owns Diesel Recovery */
    return s==='recovery' ? 'finance' : s; });
  const hasDom = !!(DOMS && DOMS.has(domain));
  const mode = domain==='purchase' ? 'purchase' : 'sales';
  const setMode = m => setDomain(m);
  const [wspace,setWspace]=icpSt(()=>localStorage.getItem('omIntelWorkspace')||'intel');
  const [period,setPeriod]=icpSt(()=>smartPeriod(app.companyId));
  const [cmpId,setCmpId]=icpSt('prev');
  const [cmpPickMode,setCmpPickMode]=icpSt(false);
  const [cmpCustomPeriod,setCmpCustomPeriod]=icpSt(null);
  const [cf,setCfState]=icpSt({});
  const [cfLbl,setCfLbl]=icpSt({});
  const [grain,setGrain]=icpSt('auto');
  const [stack,setStack]=icpSt([]);
  const [boot,setBoot]=icpSt(true);
  const [q,setQ]=icpSt('');
  const [pOpen,setPOpen]=icpSt(false); const [cOpen,setCOpen]=icpSt(false); const [sOpen,setSOpen]=icpSt(false);
  const pRef=icpRef(), pPanel=icpRef(), cRef=icpRef(), cPanel=icpRef(), sRef=icpRef(), sPanel=icpRef();

  /* live: any ERP mutation re-derives everything.
     Coalesced on a short timer so a burst of writes from the background
     sync engines costs one recompute, not one per write. */
  icpEf(()=>{
    let t=0;
    const unsub=Store.on(()=>{ clearTimeout(t); t=setTimeout(()=>setVer(v=>v+1),180); });
    return ()=>{ clearTimeout(t); unsub(); };
  },[]);
  icpEf(()=>{ const t=setTimeout(()=>setBoot(false),520); return ()=>clearTimeout(t); },[]);
  icpEf(()=>{ localStorage.setItem('omIntelDomain',domain); },[domain]);
  icpEf(()=>{ localStorage.setItem('omIntelWorkspace',wspace); },[wspace]);
  const firstCo=icpRef(companyId);
  icpEf(()=>{ if(firstCo.current!==companyId){ firstCo.current=companyId; setPeriod(smartPeriod(companyId)); clearCF(); } },[companyId]);
  icpEf(()=>{
    const h=e=>{
      if(pRef.current&&!pRef.current.contains(e.target)&&pPanel.current&&!pPanel.current.contains(e.target)) setPOpen(false);
      if(cRef.current&&!cRef.current.contains(e.target)&&cPanel.current&&!cPanel.current.contains(e.target)) setCOpen(false);
      if(sRef.current&&!sRef.current.contains(e.target)&&sPanel.current&&!sPanel.current.contains(e.target)) setSOpen(false);
    };
    document.addEventListener('mousedown',h); return ()=>document.removeEventListener('mousedown',h);
  },[]);

  icpEf(()=>{ if(!cOpen) setCmpPickMode(false); },[cOpen]);
  const cmpMenu = icpMemo(()=>IEc.compareMenu(period),[period.from,period.to,period.kind]);
  const cmpOpt = cmpMenu.find(o=>o.id===cmpId) || cmpMenu[0];
  const cmpPeriod = cmpId==='pick' ? cmpCustomPeriod : (cmpOpt ? cmpOpt.period : null);

  const setCF=(k,v,label)=>{
    setCfState(p=>{ const n=Object.assign({},p); if(v==null||n[k]===v) delete n[k]; else n[k]=v; return n; });
    setCfLbl(p=>{ const n=Object.assign({},p); if(v==null||p[k+'_v']===v){ delete n[k]; delete n[k+'_v']; } else { n[k]=label; n[k+'_v']=v; } return n; });
  };
  const clearCF=()=>{ setCfState({}); setCfLbl({}); };
  const push = node => setStack(s=>s.concat([node]));
  const popTo = i => setStack(s=>s.slice(0,i+1));

  /* ── the single derivation pass (memoised on every input incl. ver) ──── */
  const ctx = icpMemo(()=>{
    const ds = IEc.dataset(companyId, period, cf);
    const cur = IEc.metrics(ds);
    const dsPrev = cmpPeriod ? IEc.dataset(companyId, cmpPeriod, cf) : null;
    const prev = dsPrev ? IEc.metrics(dsPrev) : null;
    const ser = IEc.series(companyId, period, cf, grain);
    const cmpSer = cmpPeriod ? IEc.series(companyId, cmpPeriod, cf, ser.grain) : null;
    const matRows = IEc.splitBy(ds,'material',mode);
    const matPrev = dsPrev ? IEc.splitBy(dsPrev,'material',mode) : null;
    const custRows = IEc.splitBy(ds,'customer','sales');
    const vendRows = IEc.splitBy(ds,'vendor','purchase');
    const crusherRows = IEc.splitBy(ds,'crusher',mode);
    const pats = IEc.patterns(companyId, cf, mode);
    const seas = IEc.seasonal(companyId, cf, mode);
    const health = IEc.healthScore(cur, prev, ds, pats);
    const vk = mode==='purchase'?'purchaseValue':'revenue';
    const fc = IEc.forecast(ser.points.map(p=>p.m[vk]), 3, { season: ser.grain==='month'?12:ser.grain==='cycle'?24:0 });
    const ins = IEc.insights({ cur, prev, ds, mode, matRows, custRows, vendRows, pats, fc, health, seas,
      cmpLabel: cmpPeriod?cmpPeriod.label:'the comparison window' });
    return { companyId, mode, period, cmpPeriod, cf, ds, cur, prev, ser, cmpSer, matRows, matPrev,
             custRows, vendRows, crusherRows, pats, seas, health, fc, ins, push, setCF, grain, setGrain };
  },[companyId, mode, period.from, period.to, period.kind, cmpPeriod&&cmpPeriod.from, cmpPeriod&&cmpPeriod.to, JSON.stringify(cf), grain, ver]);

  const searchIdx = icpMemo(()=>IEc.searchIndex(companyId),[companyId,ver]);
  const years = icpMemo(()=>IEc.allYears(companyId),[companyId,ver]);
  const [favs,setFavs]=icpSt(()=>{ try{ return JSON.parse(localStorage.getItem('omIntelFavs')||'[]'); }catch(e){ return []; } });
  const [recent,setRecent]=icpSt(()=>{ try{ return JSON.parse(localStorage.getItem('omIntelRecent')||'[]'); }catch(e){ return []; } });
  const isFav = p => favs.some(f=>f.from===p.from&&f.to===p.to);
  function toggleFav(p){
    setFavs(f=>{ const on=f.some(x=>x.from===p.from&&x.to===p.to);
      const n = on ? f.filter(x=>!(x.from===p.from&&x.to===p.to)) : [p].concat(f).slice(0,10);
      localStorage.setItem('omIntelFavs',JSON.stringify(n)); return n; });
  }
  function pushRecent(p){
    setRecent(r=>{ const n=[p].concat(r.filter(x=>!(x.from===p.from&&x.to===p.to))).slice(0,6);
      localStorage.setItem('omIntelRecent',JSON.stringify(n)); return n; });
  }

  function scrollTo(id){
    const el=document.getElementById(id); const box=document.querySelector('.pg-body');
    if(!el||!box) return;
    box.scrollTo({ top: Math.max(0, el.offsetTop - 96), behavior:'smooth' });
  }
  function onSearchPick(x){
    setSOpen(false); setQ('');
    if(x.type==='material'){ setCF('materialId',x.id,x.label); scrollTo('i-material'); }
    else if(x.type==='customer'){ setMode('sales'); setCF('customerId',x.id,x.label); scrollTo('i-party'); }
    else if(x.type==='vendor'){ setMode('purchase'); setCF('vendorId',x.id,x.label); scrollTo('i-party'); }
    else if(x.type==='crusher'){ setCF('crusherSite',x.id,x.label); scrollTo('i-ops'); }
    else if(x.type==='transporter'){ setCF('transporter',x.label,x.label); scrollTo('i-ops'); }
    else if(x.type==='vehicle'){ setCF('vehicleFull',x.id,x.label); scrollTo('i-ops'); }
    else if(x.type==='plant'){ scrollTo('i-ops'); }
    else if(x.type==='salesOrder'){ setMode('sales'); setCF('id',x.id,x.label); scrollTo('i-party'); }
    else if(x.type==='purchaseOrder'){ setMode('purchase'); setCF('id',x.id,x.label); scrollTo('i-party'); }
    else if(x.type==='month'){ const mi=+x.id.slice(1); setPeriod(IEc.Periods.month(new Date().getFullYear(),mi)); }
    else if(x.type==='quarter'){ const qn=+x.id.slice(1); setPeriod(IEc.Periods.quarter(new Date().getFullYear(),qn)); }
    else if(x.type==='year'){ setPeriod(IEc.Periods.year(+x.id.slice(1))); }
    else if(x.type==='metric'){ scrollTo(x.id==='forecast'?'i-forecast':x.id==='recovery'?'i-ops':x.id==='purchase'?'i-performance':'i-performance'); }
  }
  function exportSummary(){
    const keys=IEc.metricList(mode);
    const rows=keys.map(k=>[IEc.METRICS[k].label, ctx.cur[k], ctx.prev?ctx.prev[k]:'', ctx.prev&&ctx.prev[k]?(((ctx.cur[k]-ctx.prev[k])/Math.abs(ctx.prev[k])*100).toFixed(2)+'%'):'']);
    const esc=v=>'"'+String(v==null?'':v).replace(/"/g,'""')+'"';
    const txt=[['Metric',period.label,cmpPeriod?cmpPeriod.label:'—','Change'].map(esc).join(',')].concat(rows.map(r=>r.map(esc).join(','))).join('\n');
    const a=document.createElement('a');
    a.href=URL.createObjectURL(new Blob(['\ufeff'+txt],{type:'text/csv;charset=utf-8'}));
    a.download='OM-Analytics-'+mode+'-'+period.from+'_'+period.to+'.csv';
    document.body.appendChild(a); a.click(); setTimeout(()=>{URL.revokeObjectURL(a.href);a.remove();},400);
    window.toast&&window.toast('Summary exported','ok');
  }
  const chips = Object.keys(cf).filter(k=>cf[k]!=null);
  const modeColor = window.IC.MODE_COLOR[mode];

  return (
    <div className="intel" data-mode={mode}>
      {/* ── Hero ─────────────────────────────────────────────────────── */}
      <div className="i-hero">
        <div className="i-hero-top">
          <div style={{minWidth:0}}>
            <div className="i-eyebrow"><i></i>{wspace==='studio'&&!hasDom?'Executive Decision Intelligence':'Analytics & Intelligence Center'}</div>
            {hasDom ? (
              <div className="i-sub" style={{marginTop:9}}>
                One intelligence layer over the whole ERP. Switch workspace below — sales, procurement, customers, vendors, settlements, diesel, logistics, inventory and finance all derive from the same live records, under the same period and comparison.
              </div>
            ) : (<>
              <div className="i-title">{wspace==='studio'?'Analysis Studio':(mode==='purchase'?'Procurement Intelligence':'Business Intelligence')}</div>
              <div className="i-sub">
                {wspace==='studio'
                  ? 'Beyond reporting: simulate an assumption, decompose what changed, read every forecast model\u2019s reasoning, scan for value and exposure, and annotate the live series. Every panel derives from the same ERP records \u2014 nothing is stored, nothing is written back.'
                  : 'A live derivation layer over every ERP module \u2014 sales, purchases, diesel, recovery, transfers, debris and settlements. Nothing here is stored or copied: change a record anywhere in the ERP and every number on this page moves with it.'}
              </div>
            </>)}
          </div>
          {!hasDom && (
            <div style={{display:'flex',flexDirection:'column',gap:8,alignItems:'flex-end'}}>
              <window.IWorkspaceSwitch value={wspace} onChange={setWspace}/>
            </div>
          )}
        </div>
        {!hasDom && <div className="i-hero-stats">
          {[['Health',ctx.health.score+' / 100',ctx.health.grade],
            [mode==='purchase'?'Purchase Value':'Revenue', window.IC.short(ctx.cur[mode==='purchase'?'purchaseValue':'revenue']), period.label],
            ['Records in scope', String((mode==='purchase'?ctx.ds.purchases:ctx.ds.sales).length), (mode==='purchase'?'purchase entries':'sales orders')],
            ['Signals', String(ctx.ins.length), 'insights generated live']].map((x,i)=>(
            <div key={i} className="i-hero-stat">
              <div className="i-hero-stat-k">{x[0]}</div>
              <div className="i-hero-stat-v">{x[1]}</div>
              <div className="i-hero-stat-s">{x[2]}</div>
            </div>
          ))}
        </div>}
        {DOMS ? <window.IDomainRail value={domain} onChange={setDomain}/> : <div style={{marginTop:12}}><IModeSwitch mode={mode} onChange={setMode}/></div>}
      </div>

      {/* ── Control bar ──────────────────────────────────────────────── */}
      <div className="i-bar">
        <div className="i-bar-in">
          <div ref={pRef}>
            <button className={'i-ctl'+(pOpen?' on':'')} onClick={()=>setPOpen(o=>!o)}>
              <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><rect x="3" y="4" width="18" height="18" rx="2"/><line x1="3" y1="10" x2="21" y2="10"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="16" y1="2" x2="16" y2="6"/></svg>
              <span className="i-ctl-lbl">Period</span><span className="i-ctl-val">{period.label}</span>
              <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M6 9l6 6 6-6"/></svg>
            </button>
            <window.FloatingLayer anchorRef={pRef} open={pOpen} align="left" offset={6} panelRef={pPanel}>
              <IPeriodPicker period={period} years={years} favorites={favs} recent={recent} onPick={p=>{ setPeriod(p); setPOpen(false); pushRecent(p); }}/>
            </window.FloatingLayer>
          </div>
          <button className={'i-fav-star'+(isFav(period)?' on':'')} onClick={()=>toggleFav(period)} title={isFav(period)?'Remove from favourites':'Save as favourite period'}>
            <svg viewBox="0 0 24 24" fill={isFav(period)?'currentColor':'none'} stroke="currentColor" strokeWidth="2"><path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01z"/></svg>
          </button>
          <div ref={cRef}>
            <button className={'i-ctl'+(cOpen?' on':'')} onClick={()=>setCOpen(o=>!o)}>
              <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M17 3l4 4-4 4"/><path d="M21 7H8"/><path d="M7 21l-4-4 4-4"/><path d="M3 17h13"/></svg>
              <span className="i-ctl-lbl">Compare</span><span className="i-ctl-val">{cmpPeriod?cmpPeriod.label:'None'}</span>
              <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M6 9l6 6 6-6"/></svg>
            </button>
            <window.FloatingLayer anchorRef={cRef} open={cOpen} align="left" offset={6} minWidth={260} panelRef={cPanel}>
              {cmpPickMode ? (
                <div className="i-pop" style={{width:'min(460px,92vw)'}}>
                  <div className="i-pop-hd" style={{display:'flex',alignItems:'center',gap:8}}>
                    <button className="i-crumb" onClick={()=>setCmpPickMode(false)}>‹ Back</button>
                    <span>Pick any comparison period</span>
                  </div>
                  <IPeriodPickerBody period={cmpCustomPeriod||period} years={years} onPick={p=>{ setCmpCustomPeriod(p); setCmpId('pick'); setCmpPickMode(false); setCOpen(false); }}/>
                </div>
              ) : (
                <div className="i-pop" style={{width:'min(320px,92vw)'}}>
                  <div className="i-pop-hd">Compare {period.label} with</div>
                  <div className="i-pop-body">
                    {cmpMenu.map(o=>(
                      <div key={o.id} className={'i-opt'+((cmpId===o.id&&!o.special)?' on':'')} onClick={()=>{ if(o.special){ setCmpPickMode(true); } else { setCmpId(o.id); setCOpen(false); } }}>
                        <span>{o.label}</span><em>{o.period?o.period.label:(o.special?'Month vs month, FY vs FY, custom vs custom…':'—')}</em>
                      </div>
                    ))}
                  </div>
                </div>
              )}
            </window.FloatingLayer>
          </div>
          <div className="i-search" ref={sRef}>
            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><circle cx="11" cy="11" r="7"/><path d="M21 21l-4.3-4.3"/></svg>
            <input value={q} placeholder="Search a customer, material, vendor, month or metric…"
              onChange={e=>{ setQ(e.target.value); setSOpen(true); }} onFocus={()=>setSOpen(true)}/>
            <window.FloatingLayer anchorRef={sRef} open={sOpen&&!!q.trim()} align="left" offset={6} panelRef={sPanel}>
              <ISearchResults q={q} index={searchIdx} onPick={onSearchPick}/>
            </window.FloatingLayer>
          </div>
          <button className="i-ctl" onClick={exportSummary}>
            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4M7 10l5 5 5-5M12 15V3"/></svg>Export
          </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>PDF
          </button>
        </div>
        {chips.length>0 && (
          <div className="i-chips" style={{marginTop:8}}>
            <span style={{fontSize:9.5,fontWeight:800,letterSpacing:'.08em',textTransform:'uppercase',color:'var(--txt3)'}}>Cross-filter</span>
            {chips.map(k=>(
              <span className="i-chip" key={k}>
                <span>{k==='materialId'?'Material':k==='customerId'?'Customer':k==='vendorId'?'Vendor':k==='crusherSite'?'Crusher':k==='companyId'?'Company':k}</span>
                <b>{cfLbl[k]||cf[k]}</b>
                <button onClick={()=>setCF(k,null)} aria-label="Remove filter">×</button>
              </span>
            ))}
            <button className="i-chip-clear" onClick={clearCF}>Clear all</button>
          </div>
        )}
      </div>

      {/* ── Sections ─────────────────────────────────────────────────── */}
      {boot ? <IBoot/> : hasDom ? (
        <window.IDomainWorkspace key={domain} id={domain} companyId={companyId} period={period}
          cmpPeriod={cmpPeriod} cf={cf} grain={grain} setGrain={setGrain} setPeriod={setPeriod} ver={ver}/>
      ) : wspace==='studio' ? (
        <div key={'studio-'+mode} id={'i-dom-panel-'+domain} role="tabpanel" aria-labelledby={'i-dom-tab-'+domain} tabIndex={-1} style={{animation:'iSwap .5s cubic-bezier(.16,1,.3,1) both'}}>
          <window.AnalysisStudio ctx={ctx}/>
        </div>
      ) : (
        <div key={mode} id={'i-dom-panel-'+domain} role="tabpanel" aria-labelledby={'i-dom-tab-'+domain} tabIndex={-1} style={{animation:'iSwap .5s cubic-bezier(.16,1,.3,1) both'}}>
          <window.ISKpis ctx={ctx}/>
          <window.ISPerformance ctx={ctx}/>
          <window.ISHealth ctx={ctx}/>
          <window.ISInsights ctx={ctx}/>
          <window.ISCompare ctx={ctx}/>
          <window.ISMaterial ctx={ctx}/>
          <window.ISParty ctx={ctx}/>
          <window.ISPatterns ctx={ctx}/>
          <window.ISCycle ctx={ctx}/>
          <window.ISForecast ctx={ctx}/>
          <window.ISSeasonal ctx={ctx}/>
          <window.ISOps ctx={ctx}/>
        </div>
      )}

      {stack.length>0 && (
        <window.IntelDrill stack={stack} mode={mode} companyId={companyId}
          onPush={push} onPopTo={popTo} onClose={()=>setStack([])}/>
      )}

      <style>{'@keyframes iSwap{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}'}</style>
    </div>
  );
}

Object.assign(window, { IntelCenterPage, IModeSwitch, IPeriodPicker, IPeriodPickerBody });
