/* App shell ==========================================================
   Global context provider (Account + Date Range + scope + sidebar) →
   collapsible Sidebar with the fixed nav hierarchy → master controls →
   Workspace router. Every view reads useGlobal() so a change to the
   Account or Date Range instantly re-derives all data.
=================================================================== */

/* ---- Date helpers + Meta-style presets ---- */
const TODAY_ANCHOR = new Date(); // live: tracks the real current date
const _d = (d)=>{ const x=new Date(d); x.setHours(0,0,0,0); return x; };
function addDays(d,n){ const x=_d(d); x.setDate(x.getDate()+n); return x; }
function sameDay(a,b){ return !!(a&&b) && _d(a).getTime()===_d(b).getTime(); }
function fmtMD(d){ return _d(d).toLocaleDateString('en-US',{month:'short',day:'numeric'}); }
function fmtMDY(d){ return _d(d).toLocaleDateString('en-US',{month:'short',day:'numeric',year:'numeric'}); }
function diffDays(a,b){ return Math.round((_d(b)-_d(a))/86400000); }

const DATE_PRESETS = [
  { id:'today',     label:'Today',        range:()=>[TODAY_ANCHOR, TODAY_ANCHOR] },
  { id:'yest',      label:'Yesterday',    range:()=>{ const y=addDays(TODAY_ANCHOR,-1); return [y,y]; } },
  { id:'7d',        label:'Last 7 days',  range:()=>[addDays(TODAY_ANCHOR,-6), TODAY_ANCHOR] },
  { id:'14d',       label:'Last 14 days', range:()=>[addDays(TODAY_ANCHOR,-13), TODAY_ANCHOR] },
  { id:'28d',       label:'Last 28 days', range:()=>[addDays(TODAY_ANCHOR,-27), TODAY_ANCHOR] },
  { id:'30d',       label:'Last 30 days', range:()=>[addDays(TODAY_ANCHOR,-29), TODAY_ANCHOR] },
  { id:'thisweek',  label:'This week',    range:()=>{ const s=addDays(TODAY_ANCHOR,-TODAY_ANCHOR.getDay()); return [s, TODAY_ANCHOR]; } },
  { id:'lastweek',  label:'Last week',    range:()=>{ const e=addDays(TODAY_ANCHOR,-TODAY_ANCHOR.getDay()-1); return [addDays(e,-6), e]; } },
  { id:'thismonth', label:'This month',   range:()=>[new Date(TODAY_ANCHOR.getFullYear(),TODAY_ANCHOR.getMonth(),1), TODAY_ANCHOR] },
  { id:'lastmonth', label:'Last month',   range:()=>[new Date(TODAY_ANCHOR.getFullYear(),TODAY_ANCHOR.getMonth()-1,1), new Date(TODAY_ANCHOR.getFullYear(),TODAY_ANCHOR.getMonth(),0)] },
  { id:'maximum',   label:'Maximum',      range:()=>[new Date(2025,7,1), TODAY_ANCHOR] },
];
function presetRange(id){ const p=DATE_PRESETS.find(x=>x.id===id); return p?p.range():DATE_PRESETS[5].range(); }
function matchPreset(s,e){ const p=DATE_PRESETS.find(x=>{ const [a,b]=x.range(); return sameDay(a,s)&&sameDay(b,e); }); return p?p.id:'custom'; }
function presetLabel(dr){ const p=DATE_PRESETS.find(x=>x.id===dr.preset); return p?p.label:'Custom'; }
function formatRange(dr){
  if(!dr) return 'Last 30 days';
  const s=new Date(dr.start), e=new Date(dr.end);
  if(sameDay(s,e)) return fmtMD(s);
  return (s.getFullYear()!==e.getFullYear()) ? `${fmtMDY(s)} – ${fmtMDY(e)}` : `${fmtMD(s)} – ${fmtMD(e)}`;
}
function chartRangeFor(dr){ const n=diffDays(new Date(dr.start),new Date(dr.end))+1; if(n<=7)return '7d'; if(n<=14)return '14d'; return '30d'; }

/* ===================== Global context ============================= */
const GlobalContext = React.createContext(null);
function useGlobal(){ return React.useContext(GlobalContext); }

function GlobalProvider({ currentUser, integrations, brand, children }){
  const myAccounts = useMemo(()=>accessibleAccounts(currentUser), [currentUser]);
  const [accountId, setAccountId] = useState(()=>(myAccounts[0]||ACCOUNTS[0]||{id:null}).id);
  const [dateRange, setDateRange] = useState(()=>{ const [s,e]=presetRange('30d'); return { preset:'30d', start:+s, end:+e, compare:false }; });
  const range = dateRange.preset;
  const setRange = (preset)=>{ const [s,e]=presetRange(preset); setDateRange(d=>({ preset, start:+s, end:+e, compare:d.compare })); };
  /* Reporter role: Report Builder is the ONLY workspace — start there and
     route-guard every other scope. */
  const isReporter = !!currentUser && currentUser.role === 'reporter';
  const [scope, setScope]   = useState(isReporter ? 'reports' : 'overview');
  useEffect(()=>{ if (isReporter && scope !== 'reports') setScope('reports'); }, [isReporter, scope]);
  const [search, setSearch] = useState('');
  const [collapsed, setCollapsed] = useState(true);
  const [mobileNav, setMobileNav] = useState(false);
  const [moduleAll, setModuleAll] = useState(loadModuleSettings);

  /* keep account valid if access changes */
  useEffect(()=>{ const fb=(myAccounts[0]||ACCOUNTS[0]); if(fb && !myAccounts.find(a=>a.id===accountId)) setAccountId(fb.id); }, [myAccounts]);

  const moduleSettings = moduleSettingsFor(moduleAll, accountId);
  const setModuleSettings = (s)=> setModuleAll(prev=>{ const next={...prev,[accountId]:s}; saveLS(MODULE_LS, next); return next; });

  /* Render money in the selected account's real currency (SAR/EGP/USD…). */
  const activeAccount = myAccounts.find(a=>a.id===accountId) || ACCOUNTS.find(a=>a.id===accountId);
  setActiveCurrency(activeAccount?.currency || 'USD');
  window.ACTIVE_ACCOUNT_ID = accountId;   // drives per-account metric blocklist (metricHiddenHere)

  const feeds = connectedPlatforms(integrations);

  /* Load the live data bundles the current view needs (overview + scoped platform). */
  const platformScope = scope.startsWith('platform:') ? scope.split(':')[1] : 'overview';
  useEnsureData(accountId, platformScope, dateRange);

  const value = {
    currentUser, myAccounts, feeds, isReporter,
    accountId, setAccountId, range, setRange, dateRange, setDateRange,
    scope, setScope, search, setSearch,
    collapsed, setCollapsed,
    mobileNav, setMobileNav,
    moduleSettings, setModuleSettings,
    brand: brand || loadBranding(),
  };
  return <GlobalContext.Provider value={value}>{children}</GlobalContext.Provider>;
}

/* ===================== Master controls =========================== */
const _initials = (name)=> String(name||'?').trim().split(/\s+/).map(s=>s[0]||'').slice(0,2).join('').toUpperCase() || '?';

function AccountSwitcher(){
  const { accountId, setAccountId, myAccounts } = useGlobal();
  const [q, setQ] = useState('');
  const list = (myAccounts && myAccounts.length) ? myAccounts : ACCOUNTS;
  const acc = list.find(a=>a.id===accountId) || list[0] || { name:'—', handle:'', tier:'' };
  const initial = _initials(acc.name);
  const shown = q.trim()
    ? list.filter(a => (String(a.name||'')+' '+String(a.handle||'')+' '+String(a.tier||'')).toLowerCase().includes(q.trim().toLowerCase()))
    : list;
  return (
    <Dropdown align="left" width={320} trigger={
      <button className="group inline-flex items-center gap-2 sm:gap-2.5 h-10 pl-1 pr-2 sm:pr-3 rounded-xl border border-ink-200 hover:border-ink-300 dark:border-white/10 dark:hover:border-white/20 bg-white dark:bg-ink-900/60 transition whitespace-nowrap min-w-0 max-w-[180px] sm:max-w-none">
        <span className="inline-flex items-center justify-center w-8 h-8 rounded-lg bg-gradient-to-br from-accent-500 to-accent-700 text-white font-bold text-[12px] font-mono flex-shrink-0">{initial}</span>
        <span className="flex flex-col items-start leading-tight min-w-0">
          <span className="text-[13px] font-semibold truncate max-w-[110px] sm:max-w-none">{acc.name}</span>
          <span className="text-[10.5px] text-ink-500 dark:text-ink-300 font-mono truncate max-w-[110px] sm:max-w-none">{acc.handle} · {acc.tier}</span>
        </span>
        <Icon name="chev-down" size={14} className="ml-0.5 sm:ml-1 text-ink-400 flex-shrink-0"/>
      </button>
    }>
      {(close)=>(
        <div>
          <div className="px-2 pt-1.5 pb-1 text-[10.5px] uppercase font-semibold tracking-wide text-ink-400">Ad Accounts</div>
          <div className="px-1.5 pb-1.5">
            <div className="flex items-center gap-1.5 h-8 px-2 rounded-lg border border-ink-200 dark:border-white/10 bg-ink-50/60 dark:bg-white/5 focus-within:border-accent-400">
              <Icon name="search" size={13} className="text-ink-400 flex-shrink-0"/>
              <input autoFocus value={q} onChange={e=>setQ(e.target.value)}
                onKeyDown={e=>{ if(e.key==='Enter' && shown.length){ setAccountId(shown[0].id); setQ(''); close(); } }}
                placeholder="Search accounts…"
                className="w-full bg-transparent outline-none text-[12.5px] placeholder:text-ink-400"/>
              {q && <button onClick={()=>setQ('')} className="text-ink-400 hover:text-ink-600"><Icon name="x" size={12}/></button>}
            </div>
          </div>
          <div className="max-h-[320px] overflow-y-auto scroll-soft">
          {shown.length===0 && <div className="px-3 py-4 text-[12px] text-ink-400 text-center">No accounts match “{q}”</div>}
          {shown.map(a => {
            const init = _initials(a.name);
            const active = a.id === accountId;
            return (
              <button key={a.id} onClick={()=>{ setAccountId(a.id); setQ(''); close(); }}
                className={`w-full flex items-center gap-2.5 px-2 py-2 rounded-lg transition text-left ${active?'bg-accent-50 dark:bg-accent-500/10':'hover:bg-ink-100 dark:hover:bg-white/5'}`}>
                <span className="inline-flex items-center justify-center w-7 h-7 rounded-md bg-ink-900 text-white dark:bg-white dark:text-ink-900 font-bold text-[10.5px] font-mono">{init}</span>
                <span className="flex-1 min-w-0">
                  <div className="text-[12.5px] font-semibold truncate">{a.name}</div>
                  <div className="text-[10.5px] text-ink-500 dark:text-ink-300 font-mono">{a.handle} · {a.tier}</div>
                </span>
                {active && <Icon name="check" size={14} className="text-accent-600 dark:text-accent-300"/>}
              </button>
            );
          })}
          </div>
          <div className="border-t border-ink-100 dark:border-white/5 my-1"/>
          <div className="px-2 py-1.5 text-[10.5px] font-mono text-ink-400">{shown.length} of {ACCOUNTS.length} accounts · access set in Admin</div>
        </div>
      )}
    </Dropdown>
  );
}

/* Meta Ads Manager-style calendar month */
function CalMonth({ view, sel, hover, onPick, onHover }){
  const y=view.getFullYear(), m=view.getMonth();
  const lead=new Date(y,m,1).getDay();           // 0=Sun
  const dim=new Date(y,m+1,0).getDate();
  const cells=[];
  for(let i=0;i<lead;i++) cells.push(null);
  for(let d=1;d<=dim;d++) cells.push(new Date(y,m,d));
  // resolve the active [a,b] band (committed end, or hover preview)
  let a=sel.start, b=sel.end;
  if(a && !b && hover){ if(_d(hover)<_d(a)){ b=a; a=hover; } else { b=hover; } }
  const within=(d)=> a&&b && _d(d)>=_d(a) && _d(d)<=_d(b);
  return (
    <div className="w-[224px]">
      <div className="text-center text-[12.5px] font-semibold mb-2">{view.toLocaleDateString('en-US',{month:'long',year:'numeric'})}</div>
      <div className="grid grid-cols-7">
        {['S','M','T','W','T','F','S'].map((w,i)=><div key={i} className="text-[10px] text-ink-400 text-center font-semibold h-6 flex items-center justify-center">{w}</div>)}
        {cells.map((d,i)=>{
          if(!d) return <div key={i} className="h-8"/>;
          const disabled = _d(d)>_d(TODAY_ANCHOR);
          const isStart=sameDay(d,a), isEnd=sameDay(d,b), inb=within(d), single=isStart&&isEnd;
          const isToday=sameDay(d,TODAY_ANCHOR);
          return (
            <div key={i} className={`h-8 flex items-center justify-center
              ${inb && !single ? 'bg-accent-100 dark:bg-accent-500/25' : ''}
              ${inb && isStart && !single ? 'rounded-l-full' : ''} ${inb && isEnd && !single ? 'rounded-r-full' : ''}`}>
              <button disabled={disabled} onMouseEnter={()=>onHover(d)} onClick={()=>onPick(d)}
                className={`w-8 h-8 text-[12px] flex items-center justify-center rounded-full transition
                  ${isStart||isEnd ? 'bg-accent-500 text-white font-semibold' : disabled ? 'text-ink-300 dark:text-white/15 cursor-not-allowed' : 'hover:bg-ink-200 dark:hover:bg-white/15 cursor-pointer'}
                  ${isToday&&!isStart&&!isEnd ? 'ring-1 ring-accent-400' : ''}`}>
                {d.getDate()}
              </button>
            </div>
          );
        })}
      </div>
    </div>
  );
}

function DateRangePicker(){
  const { dateRange, setDateRange } = useGlobal();
  const [open,setOpen]   = useState(false);
  const [sel,setSel]     = useState({ start:new Date(dateRange.start), end:new Date(dateRange.end) });
  const [hover,setHover] = useState(null);
  const [compare,setCompare] = useState(!!dateRange.compare);
  const [view,setView]   = useState(()=>{ const e=new Date(dateRange.end); return new Date(e.getFullYear(), e.getMonth()-1, 1); });
  const ref = useRef(null);

  const onReset = ()=>{
    setSel({ start:new Date(dateRange.start), end:new Date(dateRange.end) });
    setCompare(!!dateRange.compare);
    const e=new Date(dateRange.end); setView(new Date(e.getFullYear(), e.getMonth()-1, 1));
    setHover(null);
  };
  useEffect(()=>{ if(open) onReset(); }, [open]);
  useEffect(()=>{
    if(!open) return;
    const h=(e)=>{ if(ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener('mousedown',h); return ()=>document.removeEventListener('mousedown',h);
  }, [open]);

  const activePreset = (sel.start&&sel.end) ? matchPreset(sel.start, sel.end) : 'custom';

  const pickPreset = (p)=>{
    const [s,e]=p.range(); setSel({ start:s, end:e }); setHover(null);
    setView(new Date(e.getFullYear(), e.getMonth()-1, 1));
  };
  const pickDay = (d)=>{
    if(!sel.start || sel.end){ setSel({ start:d, end:null }); }   // begin a new range
    else if(_d(d) < _d(sel.start)){ setSel({ start:d, end:null }); }
    else { setSel({ start:sel.start, end:d }); }
  };
  const apply = ()=>{
    const s=sel.start, e=sel.end||sel.start;
    setDateRange({ preset: matchPreset(s,e), start:+_d(s), end:+_d(e), compare });
    setOpen(false);
  };

  const navMax = new Date(TODAY_ANCHOR.getFullYear(), TODAY_ANCHOR.getMonth(), 1);
  const canFwd = +new Date(view.getFullYear(), view.getMonth()+1, 1) < +navMax;

  return (
    <div className="relative" ref={ref}>
      <button onClick={()=>setOpen(o=>!o)}
        className={`inline-flex items-center gap-2 h-9 pl-2.5 pr-2.5 rounded-lg border transition whitespace-nowrap ${open?'border-accent-300 bg-accent-50/60 dark:border-accent-500/40 dark:bg-accent-500/10':'border-ink-200 hover:bg-ink-100 dark:border-white/10 dark:hover:bg-white/5'}`}>
        <Icon name="calendar" size={14} className="text-ink-500 dark:text-ink-300"/>
        <span className="text-[12.5px] font-medium leading-tight text-left whitespace-nowrap">
          <div className="whitespace-nowrap">{presetLabel(dateRange)}</div>
          <div className="text-[10.5px] text-ink-500 dark:text-ink-300 font-mono -mt-0.5 whitespace-nowrap">{formatRange(dateRange)}</div>
        </span>
        <Icon name="chev-down" size={13} className={`text-ink-400 ml-1 transition-transform ${open?'rotate-180':''}`}/>
      </button>

      {open && (
        <div className="absolute right-0 mt-2 z-40 origin-top-right animate-dropin rounded-xl border border-ink-200 dark:border-white/10 bg-white dark:bg-ink-800 shadow-float overflow-hidden flex flex-col sm:flex-row w-[min(92vw,640px)]">
          {/* preset rail */}
          <div className="sm:w-[176px] border-b sm:border-b-0 sm:border-r border-ink-100 dark:border-white/10 p-2 flex sm:flex-col gap-0.5 overflow-x-auto sm:overflow-visible scroll-none">
            {DATE_PRESETS.map(p=>(
              <button key={p.id} onClick={()=>pickPreset(p)}
                className={`text-left px-2.5 h-8 rounded-md text-[12.5px] font-medium whitespace-nowrap flex-shrink-0 transition ${activePreset===p.id?'bg-accent-500 text-white':'text-ink-700 dark:text-ink-200 hover:bg-ink-100 dark:hover:bg-white/5'}`}>
                {p.label}
              </button>
            ))}
          </div>

          {/* calendar side */}
          <div className="flex-1 p-3 min-w-0">
            {/* date inputs */}
            <div className="flex items-center gap-2 mb-3">
              <div className="flex-1 h-9 px-3 rounded-lg border border-ink-200 dark:border-white/10 flex items-center text-[12.5px] font-medium">{sel.start?fmtMDY(sel.start):'—'}</div>
              <Icon name="arrow-right" size={14} className="text-ink-400 flex-shrink-0"/>
              <div className="flex-1 h-9 px-3 rounded-lg border border-ink-200 dark:border-white/10 flex items-center text-[12.5px] font-medium">{sel.end?fmtMDY(sel.end):(sel.start?'Select end':'—')}</div>
            </div>

            {/* months */}
            <div className="relative" onMouseLeave={()=>setHover(null)}>
              <button onClick={()=>setView(new Date(view.getFullYear(),view.getMonth()-1,1))}
                className="absolute -top-0.5 left-0 h-7 w-7 grid place-items-center rounded-md hover:bg-ink-100 dark:hover:bg-white/10 text-ink-500"><Icon name="chev-left" size={16}/></button>
              <button onClick={()=>canFwd&&setView(new Date(view.getFullYear(),view.getMonth()+1,1))} disabled={!canFwd}
                className={`absolute -top-0.5 right-0 h-7 w-7 grid place-items-center rounded-md text-ink-500 ${canFwd?'hover:bg-ink-100 dark:hover:bg-white/10':'opacity-30 cursor-not-allowed'}`}><Icon name="chev-right" size={16}/></button>
              <div className="flex gap-4 justify-center">
                <CalMonth view={view} sel={sel} hover={hover} onPick={pickDay} onHover={setHover}/>
                <div className="hidden sm:block"><CalMonth view={new Date(view.getFullYear(),view.getMonth()+1,1)} sel={sel} hover={hover} onPick={pickDay} onHover={setHover}/></div>
              </div>
            </div>

            {/* footer */}
            <div className="flex items-center justify-between mt-3 pt-3 border-t border-ink-100 dark:border-white/10 gap-2 flex-wrap">
              <label className="inline-flex items-center gap-2 text-[12.5px] font-medium cursor-pointer select-none">
                <Toggle checked={compare} onChange={setCompare} size="sm"/>
                <span>Compare to previous period</span>
              </label>
              <div className="flex items-center gap-2 ml-auto">
                <Btn size="sm" variant="ghost" onClick={onReset}>Reset</Btn>
                <Btn size="sm" variant="accent" onClick={apply} disabled={!sel.start}>Update</Btn>
              </div>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

function GlobalSearch(){
  const { search, setSearch } = useGlobal();
  return (
    <div className="relative h-9 w-[200px] hidden md:block">
      <Icon name="search" size={14} className="absolute left-2.5 top-1/2 -translate-y-1/2 text-ink-400"/>
      <input value={search} onChange={e=>setSearch(e.target.value)} placeholder="Search…"
        className="w-full h-full pl-8 pr-3 rounded-lg border border-ink-200 dark:border-white/10 bg-white dark:bg-ink-900/40 text-[12.5px] focus:outline-none focus:border-accent-400"/>
    </div>
  );
}

function WorkspaceUserMenu({ user, onOpenAdmin, onSignOut, canAdmin }){
  return (
    <Dropdown align="right" width={252} trigger={
      <button className="inline-flex items-center gap-2 h-10 pl-1 pr-2 rounded-xl border border-ink-200 hover:border-ink-300 dark:border-white/10 dark:hover:border-white/20 bg-white dark:bg-ink-900/60 transition">
        <Avatar user={user} size={30}/><Icon name="chev-down" size={13} className="text-ink-400"/>
      </button>
    }>
      {(close)=>(
        <div>
          <div className="px-2.5 py-2.5 flex items-center gap-2.5">
            <Avatar user={user} size={40}/>
            <div className="min-w-0"><div className="text-[13px] font-semibold truncate">{user.name}</div><div className="text-[11px] text-ink-500 dark:text-ink-300 font-mono truncate">{user.email}</div></div>
          </div>
          <div className="px-2.5 pb-2"><RoleBadge role={user.role}/></div>
          <div className="border-t border-ink-100 dark:border-white/5 my-1"/>
          {canAdmin && (
            <button onClick={()=>{ close(); onOpenAdmin(); }} className="w-full flex items-center gap-2 px-2.5 py-2 text-[12.5px] hover:bg-ink-100 dark:hover:bg-white/5 rounded-lg">
              <Icon name="settings" size={14}/> Admin panel <Icon name="chev-right" size={13} className="ml-auto text-ink-400"/>
            </button>
          )}
          <div className="border-t border-ink-100 dark:border-white/5 my-1"/>
          <button onClick={()=>{ close(); onSignOut(); }} className="w-full flex items-center gap-2 px-2.5 py-2 text-[12.5px] text-rose-600 dark:text-rose-300 hover:bg-rose-50 dark:hover:bg-rose-500/10 rounded-lg">
            <Icon name="link-break" size={14}/> Sign out
          </button>
        </div>
      )}
    </Dropdown>
  );
}

function ConnectionBanner({ integrations, canAdmin, onOpenAdmin }){
  const problems = integrations.filter(i => (i.kind!=='db' && i.kind!=='custom') && (i.status!=='connected' || i.health==='degraded'));
  if (problems.length===0) return null;
  const offline = problems.filter(i=>i.status!=='connected');
  const tone = offline.length>0
    ? { bg:'bg-rose-50 dark:bg-rose-500/10', border:'border-rose-200 dark:border-rose-500/25', text:'text-rose-700 dark:text-rose-300' }
    : { bg:'bg-amber-50 dark:bg-amber-500/10', border:'border-amber-200 dark:border-amber-500/25', text:'text-amber-700 dark:text-amber-300' };
  return (
    <div className={`flex items-center gap-3 px-4 py-3 rounded-2xl border ${tone.bg} ${tone.border}`}>
      <Icon name="alert" size={16} className={tone.text}/>
      <div className="flex-1 min-w-0">
        <div className={`text-[13px] font-semibold ${tone.text}`}>{offline.length>0?`${offline.length} connection${offline.length>1?'s':''} offline`:''}{offline.length>0&&problems.length>offline.length?' · ':''}{problems.length>offline.length?`${problems.length-offline.length} degraded`:''}</div>
        <div className="text-[12px] text-ink-600 dark:text-ink-300 flex items-center gap-2 mt-0.5 flex-wrap">
          {problems.map(i=>(<span key={i.id} className="inline-flex items-center gap-1.5"><span className="inline-flex items-center justify-center w-4 h-4 text-ink-900 dark:text-white"><BrandIcon name={PROVIDER_ICON[i.provider]||'custom'} size={14}/></span>{i.name}<span className="font-mono text-[10.5px] opacity-70">{i.status!=='connected'?'offline':'degraded'}</span></span>))}
        </div>
      </div>
      {canAdmin && <Btn size="sm" variant="subtle" icon="chev-right" onClick={onOpenAdmin}>Fix in Admin</Btn>}
    </div>
  );
}

/* ===================== Sidebar =================================== */
function SidebarItem({ icon, label, active, collapsed, onClick, indent, brandIcon, tone }){
  return (
    <button onClick={onClick} title={collapsed?label:undefined}
      className={`w-full flex items-center gap-2.5 h-9 rounded-lg text-[13px] font-medium transition text-left
        ${collapsed?'justify-center px-0':'px-2.5'} ${indent&&!collapsed?'pl-9':''}
        ${active?'bg-white dark:bg-ink-800 shadow-card text-ink-900 dark:text-white border border-ink-200 dark:border-white/10':'text-ink-500 dark:text-ink-300 hover:bg-white/70 dark:hover:bg-white/5'}`}>
      {brandIcon
        ? <span className="inline-flex items-center justify-center w-[18px] h-[18px] text-ink-900 dark:text-white flex-shrink-0"><BrandIcon name={brandIcon} size={17}/></span>
        : <Icon name={icon} size={17} className="flex-shrink-0" style={tone?{color:tone}:undefined}/>}
      {!collapsed && <span className="truncate">{label}</span>}
    </button>
  );
}

function Sidebar({ onOpenAdmin, canAdmin }){
  const { scope, setScope, collapsed, setCollapsed, mobileNav, setMobileNav, moduleSettings, feeds, accountId, currentUser, brand, isReporter } = useGlobal();
  const [platOpen, setPlatOpen] = useState(true);
  const canSettings = can(currentUser, 'settings.manage');
  const dataVersion = useDataVersion();  /* re-render the rail when live data lands (this <aside> sits outside the keyed <main>) */

  /* Platforms that actually have real spend for the selected account, straight
     from the ingested warehouse breakdown. This is the honest, account-scoped
     signal — a platform (e.g. X / LinkedIn) may have live data before an
     integration row advertises it in `feeds`. */
  const dataPlatforms = React.useMemo(
    () => new Set(platformBreakdown(accountId).filter(m=>Number(m.spend)>0).map(m=>m.platform)),
    [accountId, dataVersion]
  );

  /* platforms shown = enabled for account AND (have a live feed OR real data) */
  const platforms = PLATFORMS.filter(p =>
    TOGGLEABLE_PLATFORMS.includes(p.id) &&
    moduleSettings.platforms.includes(p.id) &&
    (feeds[p.id] || dataPlatforms.has(p.id))
  );
  const platActive = scope.startsWith('platform:');
  /* On mobile the drawer is always full (labels visible); collapse only applies to desktop */
  const rail = collapsed && !mobileNav;
  const go = (s)=>{ setScope(s); setMobileNav(false); };

  return (
    <>
      {/* mobile backdrop */}
      {mobileNav && <div className="fixed inset-0 z-40 bg-black/40 md:hidden" onClick={()=>setMobileNav(false)}/>}

      <aside
        style={{ width: rail?64:240, minWidth: rail?64:240 }}
        className={`z-50 md:z-auto flex flex-col overflow-hidden border-r border-ink-200 dark:border-white/10 bg-ink-50 dark:bg-ink-900 md:bg-ink-50/80 md:dark:bg-ink-900/60 backdrop-blur-sm transition-all duration-200
          fixed md:sticky inset-y-0 left-0 h-screen md:h-screen md:top-0
          ${mobileNav?'translate-x-0 shadow-2xl':'-translate-x-full'} md:translate-x-0`}>
        {/* brand */}
        <div className={`h-16 flex items-center border-b border-ink-200 dark:border-white/10 flex-shrink-0 ${rail?'justify-center px-0':'px-4 gap-2.5'}`}>
          <BrandLogo brand={brand} size={28}/>
          {!rail && <Wordmark size={17} brand={brand}/>}
          {mobileNav && <button onClick={()=>setMobileNav(false)} className="ml-auto md:hidden h-8 w-8 grid place-items-center rounded-lg hover:bg-ink-100 dark:hover:bg-white/5"><Icon name="x" size={18}/></button>}
        </div>

        <nav className="flex-1 overflow-y-auto scroll-soft p-2.5 space-y-1">
          {isReporter && (
            <SidebarItem icon="file" label="Report Builder" tone="#f59e0b" active={scope==='reports'} collapsed={rail} onClick={()=>go('reports')}/>
          )}
          {!isReporter && <React.Fragment>
          <SidebarItem icon="sparkles" label="Overview" tone="#8351ff" active={scope==='overview'} collapsed={rail} onClick={()=>go('overview')}/>

          {/* Advertising Platforms accordion */}
          <div>
            <button onClick={()=>rail?setCollapsed(false):setPlatOpen(o=>!o)} title={rail?'Advertising Platforms':undefined}
              className={`w-full flex items-center gap-2.5 h-9 rounded-lg text-[13px] font-medium transition ${rail?'justify-center px-0':'px-2.5'} ${platActive?'text-ink-900 dark:text-white':'text-ink-500 dark:text-ink-300 hover:bg-white/70 dark:hover:bg-white/5'}`}>
              <Icon name="zap" size={17} className="flex-shrink-0" style={{color:'#8351ff'}}/>
              {!rail && <><span className="truncate flex-1 text-left">Advertising Platforms</span><Icon name="chev-down" size={13} className={`transition-transform ${platOpen?'':'-rotate-90'}`}/></>}
            </button>
            {!rail && platOpen && (
              <div className="mt-1 space-y-0.5">
                {platforms.length===0 && <div className="pl-9 py-1.5 text-[11.5px] text-ink-400">No platforms enabled</div>}
                {platforms.map(p=>(
                  <SidebarItem key={p.id} brandIcon={p.icon} label={p.label} indent active={scope===`platform:${p.id}`} collapsed={false} onClick={()=>go(`platform:${p.id}`)}/>
                ))}
              </div>
            )}
            {rail && platforms.map(p=>(
              <div key={p.id} className="mt-1"><SidebarItem brandIcon={p.icon} label={p.label} active={scope===`platform:${p.id}`} collapsed onClick={()=>go(`platform:${p.id}`)}/></div>
            ))}
          </div>

          <SidebarItem icon="file" label="Report Builder" tone="#f59e0b" active={scope==='reports'} collapsed={rail} onClick={()=>go('reports')}/>
          <SidebarItem icon="image" label="Creative Preview" tone="#ec4899" active={scope==='creative'} collapsed={rail} onClick={()=>go('creative')}/>
          <SidebarItem brandIcon="ga" label="Google Analytics" active={scope==='ga'} collapsed={rail} onClick={()=>go('ga')}/>
          <SidebarItem icon="mediaplan" label="Media Plan" tone="#10b981" active={scope==='media'} collapsed={rail} onClick={()=>go('media')}/>
          {canSettings && <SidebarItem icon="settings" label="Settings" tone="#2f7bff" active={scope==='settings'} collapsed={rail} onClick={()=>go('settings')}/>}
          </React.Fragment>}
        </nav>

        {/* footer: admin + collapse */}
        <div className="p-2.5 border-t border-ink-200 dark:border-white/10 space-y-1 flex-shrink-0">
          {canAdmin && <SidebarItem icon="settings" label="Admin Panel" tone="#f59e0b" active={false} collapsed={rail} onClick={()=>{ setMobileNav(false); onOpenAdmin(); }}/>}
          <button onClick={()=>setCollapsed(c=>!c)} title="Collapse"
            className={`hidden md:flex w-full items-center gap-2.5 h-9 rounded-lg text-[12.5px] font-medium text-ink-400 hover:bg-white/70 dark:hover:bg-white/5 transition ${rail?'justify-center px-0':'px-2.5'}`}>
            <Icon name="chev-right" size={16} className={`transition-transform ${rail?'':'rotate-180'}`} style={{color:'#06b6d4'}}/>
            {!rail && <span>Collapse</span>}
          </button>
        </div>
      </aside>
    </>
  );
}

/* Small per-platform spend scorecards for the Overview — real ingested spend
   per platform for the selected account, in the account's currency. Each card
   deep-links into that platform's tab. Honest data only (spend > 0). */
function PlatformSpendCards({ accountId }){
  const { setScope } = useGlobal();
  const dataVersion = useDataVersion();
  const cards = React.useMemo(()=>{
    const rows = platformBreakdown(accountId)
      .filter(m => !['overview','google_analytics'].includes(m.platform) && Number(m.spend) > 0)
      .map(m => { const p = PLATFORMS.find(x=>x.id===m.platform) || {};
        return { id:m.platform, label:p.short || p.label || m.platform, spend:Number(m.spend), tone:p.tone || '#8351ff' }; })
      .sort((a,b)=> b.spend - a.spend);
    const total = rows.reduce((s,r)=>s+r.spend, 0) || 1;
    return rows.map(r => ({ ...r, pct: r.spend/total*100 }));
  }, [accountId, dataVersion]);

  if (cards.length === 0) return null;

  return (
    <div>
      <div className="flex items-center justify-between mb-2 px-0.5">
        <div className="text-[13px] font-semibold flex items-center gap-1.5"><Icon name="zap" size={13} style={{color:'#8351ff'}}/>Spend by platform</div>
        <span className="text-[11px] text-ink-400 font-mono">{cards.length} {cards.length===1?'platform':'platforms'}</span>
      </div>
      <div className="grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-5 gap-2.5">
        {cards.map(c => (
          <button key={c.id} onClick={()=>setScope(`platform:${c.id}`)}
            title={`View ${c.label}`}
            className="text-left rounded-xl border border-ink-200 dark:border-white/10 bg-white/70 dark:bg-white/[0.03] p-3 transition hover:border-accent-300 dark:hover:border-accent-500/40 hover:shadow-sm focus:outline-none focus-visible:ring-2 focus-visible:ring-accent-400">
            <div className="flex items-center justify-between mb-2 gap-2">
              <span className="flex items-center gap-1.5 min-w-0">
                <PlatformChip p={c.id} size={16}/>
                <span className="text-[12px] font-medium text-ink-700 dark:text-ink-200 truncate">{c.label}</span>
              </span>
              <span className="text-[10px] font-mono text-ink-400 flex-shrink-0">{c.pct.toFixed(0)}%</span>
            </div>
            <div className="text-[16px] font-semibold tabular leading-none">{fmt(c.spend,'currency')}</div>
            <div className="mt-2 h-1 rounded-full bg-ink-100 dark:bg-white/10 overflow-hidden">
              <div className="h-full rounded-full" style={{ width:`${Math.max(4,c.pct)}%`, background:displayTone(c.tone) }}/>
            </div>
          </button>
        ))}
      </div>
    </div>
  );
}

/* ===================== Overview view ============================= */
function OverviewView({ accountId, range, dateRange, dark, alerts, canEdit, moduleSettings, onOpenColumns }){
  const w = moduleSettings.widgets;
  const on = (id)=> w[id]!==false;
  const platformId = 'overview';
  const liveCount = useMemo(()=>getCampaigns(accountId,'overview').filter(c=>c.status==='active').length, [accountId]);
  const anyKpi = KPI_WIDGET_IDS.some(id=> w[id]!==false);
  const anyChartRow = on('chart') || on('anomalies') || on('platform_mix');

  return (
    <div className="space-y-4">
      {anyKpi && <BentoKPIGrid accountId={accountId} platformId={platformId} onAddCustomCol={onOpenColumns} widgets={w}/>}

      <PlatformSpendCards accountId={accountId}/>

      {anyChartRow && (
        <div className="grid grid-cols-12 gap-3">
          {on('chart') && (
            <Card className={`col-span-12 ${(on('anomalies')||on('platform_mix'))?'lg:col-span-8':''} p-5 rounded-2xl`}>
              <div className="flex items-center justify-between mb-1">
                <div>
                  <div className="text-[13px] font-semibold flex items-center gap-2">
                    {metricHiddenFor(accountId,'roas') ? 'Spend trend' : 'Spend × ROAS'}
                    <Pill tone="neutral"><PlatformChip p={platformId} size={12}/><span className="ml-1">Blended</span></Pill>
                  </div>
                  <div className="text-[11.5px] text-ink-500 dark:text-ink-300 mt-0.5">
                    {metricHiddenFor(accountId,'roas') ? 'Daily ad spend.' : 'Daily ad spend vs return on ad spend.'}
                  </div>
                </div>
                <div className="flex items-center gap-3 text-[11.5px]">
                  <div className="flex items-center gap-1.5"><span className="w-2 h-2 rounded-full bg-accent-500"/>Spend</div>
                  {!metricHiddenFor(accountId,'roas') &&
                    <div className="flex items-center gap-1.5"><span className="w-2 h-2 rounded-full bg-emerald-500"/>ROAS</div>}
                </div>
              </div>
              <SpendRoasChart accountId={accountId} platformId={platformId} range={chartRangeFor(dateRange)} dark={dark}
                hideRoas={metricHiddenFor(accountId,'roas')}/>
            </Card>
          )}
          {(on('anomalies')||on('platform_mix')) && (
            <div className={`col-span-12 ${on('chart')?'lg:col-span-4':''} grid gap-3`}>
              {on('anomalies') && (
                <Card className="p-4 rounded-2xl">
                  <div className="flex items-center justify-between mb-2"><div className="text-[13px] font-semibold flex items-center gap-1.5"><Icon name="alert" size={13} className="text-amber-500"/>Anomalies <span className="text-ink-400 font-normal text-[11px] font-mono">24h</span></div></div>
                  <div className="space-y-1.5">
                    {alerts.slice(0,3).map(a => { const tone = SEV_TONES[a.sev]; return (
                      <div key={a.id} className={`px-2.5 py-2 rounded-lg ${tone.bg} text-[11.5px] flex items-start gap-2 border ${tone.border}`}>
                        <Icon name={SEV_ICONS[a.sev]} size={12} className={`mt-0.5 ${tone.text}`}/>
                        <div className="flex-1 min-w-0"><div className={`font-semibold truncate ${tone.text}`}>{a.title}</div><div className="text-ink-600 dark:text-ink-300 truncate">{a.msg}</div></div>
                      </div>
                    ); })}
                  </div>
                </Card>
              )}
              {on('platform_mix') && (
                <Card className="p-4 rounded-2xl">
                  <div className="flex items-center justify-between mb-3"><div className="text-[13px] font-semibold">Platform mix</div><Pill tone="neutral">{formatRange(dateRange)}</Pill></div>
                  <PlatformShare accountId={accountId}/>
                </Card>
              )}
            </div>
          )}
        </div>
      )}

      {on('campaign_table') && <CampaignTable accountId={accountId} platformId={platformId} search="" canEdit={canEdit} onOpenColumns={onOpenColumns}/>}
      {on('creative') && <CreativePreview accountId={accountId} platformId={platformId}/>}

      <div className="pt-2 flex items-center justify-between text-[11.5px] text-ink-400">
        <div className="font-mono">{liveCount} active campaigns · {alerts.length} recent events</div>
        <div className="font-mono">Auto-refresh every 30s</div>
      </div>
    </div>
  );
}

/* ===================== Workspace ================================= */
function Workspace({ currentUser, integrations, onOpenAdmin, onSignOut, dark, setDark, pushAudit }){
  const g = useGlobal();
  const { scope, accountId, range, search } = g;
  const setMobileNav = g.setMobileNav;
  const canEdit = can(currentUser,'campaigns.edit');
  const canReallocate = can(currentUser,'reallocate.apply');
  const canAutomate = can(currentUser,'automations.manage');
  const canAdmin = can(currentUser,'users.manage') || can(currentUser,'integrations.manage');
  const canMediaplan = can(currentUser,'mediaplan.manage');
  const canSettings = can(currentUser,'settings.manage');

  const [showColumns, setShowColumns] = useState(false);
  const [showAutomations, setShowAutomations] = useState(false);
  const [showPalette, setShowPalette] = useState(false);
  const [showReallocator, setShowReallocator] = useState(false);
  const [customCols, setCustomCols] = useState(DEFAULT_CUSTOM_COLS);
  const [rules, setRules] = useState(DEFAULT_RULES);

  useEffect(()=>{ const onKey=(e)=>{ if((e.metaKey||e.ctrlKey)&&(e.key==='k'||e.key==='K')){ e.preventDefault(); setShowPalette(p=>!p);} }; window.addEventListener('keydown',onKey); return ()=>window.removeEventListener('keydown',onKey); }, []);

  /* alerts (live from the warehouse) + toasts */
  const dataVersion = useDataVersion();
  const [allRead, setAllRead] = useState(false);
  useEffect(()=>{ setAllRead(false); }, [accountId]);
  const alerts = useMemo(()=>{
    const a = getAlerts(accountId);
    return allRead ? a.map(x=>({ ...x, read:true })) : a;
  }, [accountId, dataVersion, allRead]);
  const [toasts, setToasts] = useState([]);
  const dismissToast = (id)=>setToasts(arr=>arr.filter(t=>t.id!==id));
  const markAllRead = ()=>setAllRead(true);

  /* account-switch toast */
  const first = useRef(true);
  useEffect(()=>{ if(first.current){ first.current=false; return; } const id='t'+Date.now(); const acc=ACCOUNTS.find(a=>a.id===accountId);
    setToasts(arr=>[...arr,{id,sev:'info',title:'Switched account',msg:`Loaded ${acc?acc.name:'account'} — refreshing data.`}]);
    setTimeout(()=>setToasts(arr=>arr.filter(x=>x.id!==id)),4000); }, [accountId]);

  /* Auto-refresh: every 10 minutes re-fetch the current account's bundles so
     the view tracks the server-side cron sync without manual clicks. */
  useEffect(()=>{
    const t = setInterval(()=>{
      try {
        RelayLive.clearAll();
        RelayLive.ensure(accountId, 'overview', g.dateRange);
        if (scope.startsWith('platform:')) RelayLive.ensure(accountId, scope.split(':')[1], g.dateRange);
      } catch(e){ console.warn('[relay] auto-refresh failed:', e); }
    }, 10 * 60 * 1000);
    return ()=>clearInterval(t);
  }, [accountId, scope, g.dateRange && g.dateRange.start, g.dateRange && g.dateRange.end]);

  /* manual Meta data refresh — server pulls fresh insights from the Graph API */
  const [syncing, setSyncing] = useState(false);
  const doRefresh = async ()=>{
    if (syncing) return;
    setSyncing(true);
    const tid = 't'+Date.now();
    try {
      const r = await RelayAPI.post('/sync/meta', { days: 7 });
      RelayLive.clearAll();
      await RelayLive.ensure(accountId, 'overview', g.dateRange);
      if (scope.startsWith('platform:')) await RelayLive.ensure(accountId, scope.split(':')[1], g.dateRange);
      const done = r && r.result && r.result.complete;
      setToasts(arr=>[...arr,{ id:tid, sev:'info', title:'Data refreshed',
        msg: done ? 'Meta insights re-pulled for the last 7 days.' : 'Partial sync — click Refresh again to continue.' }]);
    } catch(e) {
      setToasts(arr=>[...arr,{ id:tid, sev:'error', title:'Refresh failed', msg: e.message || 'Sync error' }]);
    }
    setTimeout(()=>setToasts(arr=>arr.filter(x=>x.id!==tid)), 5000);
    setSyncing(false);
  };

  /* title per scope */
  const scopeTitle = scope==='overview'?'Overview'
    : scope.startsWith('platform:')?(PLATFORMS.find(p=>p.id===scope.split(':')[1])||{}).label
    : scope==='creative'?'Creative Preview' : scope==='ga'?'Google Analytics' : scope==='media'?'Media Plan' : scope==='reports'?'Report Builder' : scope==='settings'?'Settings':'';

  return (
    <div className="flex min-h-screen text-ink-900 dark:text-ink-50">
      <Sidebar onOpenAdmin={onOpenAdmin} canAdmin={canAdmin}/>

      <div className="flex-1 min-w-0 flex flex-col">
        {/* top master controls */}
        <header className="sticky top-0 z-30 backdrop-blur-md bg-ink-50/85 dark:bg-ink-900/75 border-b border-ink-200 dark:border-white/10">
          <div className="px-3 sm:px-5 h-16 flex items-center gap-2 sm:gap-3">
            <button onClick={()=>setMobileNav(true)} className="md:hidden h-9 w-9 grid place-items-center rounded-lg border border-ink-200 dark:border-white/10 flex-shrink-0" title="Menu">
              <Icon name="menu" size={18}/>
            </button>
            <AccountSwitcher/>
            <div className="hidden lg:flex items-center gap-2 text-[12.5px] text-ink-500 dark:text-ink-300 whitespace-nowrap ml-1">
              <Icon name="chev-right" size={12} className="text-ink-400"/><span className="font-semibold text-ink-900 dark:text-white">{scopeTitle}</span>
            </div>
            <div className="flex-1"/>
            {!g.isReporter && <GlobalSearch/>}
            {!g.isReporter && <DateRangePicker/>}
            {!g.isReporter && (
              <IconButton title={syncing?'Refreshing…':'Refresh data (pull latest from Meta)'} onClick={doRefresh}>
                <Icon name="refresh" size={15} className={syncing?'animate-spin':''}/>
              </IconButton>
            )}
            <div className="hidden sm:block h-6 w-px bg-ink-200 dark:bg-white/10"/>
            <NotificationsBell alerts={alerts} onMarkAllRead={markAllRead}/>
            <IconButton title="Toggle theme" onClick={()=>setDark(d=>!d)}><Icon name={dark?'sun':'moon'} size={15}/></IconButton>
            <WorkspaceUserMenu user={currentUser} onOpenAdmin={onOpenAdmin} onSignOut={onSignOut} canAdmin={canAdmin}/>
          </div>
          {/* contextual action row for platform/overview */}
          {(scope==='overview'||scope.startsWith('platform:')) && (
            <div className="px-3 sm:px-5 h-12 flex items-center gap-2 border-t border-ink-100 dark:border-white/5">
              <div className="min-w-0 flex-1 overflow-hidden"><FreshnessChips/></div>
              {canEdit && <Btn size="sm" variant="ghost" icon="columns" onClick={()=>setShowColumns(true)} className="hidden sm:inline-flex">Columns</Btn>}
              {canReallocate && <Btn size="sm" variant="ghost" icon="sparkles" onClick={()=>setShowReallocator(true)} className="hidden sm:inline-flex">Reallocate</Btn>}
              {canAutomate && <Btn size="sm" variant="ghost" icon="zap" onClick={()=>setShowAutomations(true)} className="hidden sm:inline-flex">Automations <Pill tone="accent" className="ml-1">{rules.filter(r=>r.enabled).length}</Pill></Btn>}
            </div>
          )}
        </header>

        {/* routed content */}
        <main className="flex-1 px-3 sm:px-5 pt-4 sm:pt-5 pb-16 max-w-[1500px] w-full mx-auto">
         <div key={`${accountId}:${scope}:${dataVersion}`} className="space-y-4">
          {(scope==='overview') && <>
            <ConnectionBanner integrations={integrations} canAdmin={canAdmin} onOpenAdmin={onOpenAdmin}/>
            <OverviewView accountId={accountId} range={range} dateRange={g.dateRange} dark={dark} alerts={alerts} canEdit={canEdit} moduleSettings={g.moduleSettings} onOpenColumns={()=>setShowColumns(true)}/>
          </>}
          {scope.startsWith('platform:') && <PlatformView platform={scope.split(':')[1]} accountId={accountId} search={search} canEdit={canEdit}/>}
          {scope==='creative' && <div><div className="flex items-center gap-3 mb-4"><span className="inline-flex items-center justify-center w-10 h-10 rounded-xl bg-accent-100 dark:bg-accent-500/15 text-accent-600 dark:text-accent-300"><Icon name="image" size={22}/></span><div><h1 className="text-[20px] font-semibold tracking-tight leading-none">Creative Preview</h1><div className="text-[12px] text-ink-500 dark:text-ink-300 mt-1">Top creatives across platforms for this account</div></div></div><CreativePreview accountId={accountId} platformId="overview"/></div>}
          {scope==='reports' && <ReportsView accountId={accountId} currentUser={currentUser}/>}
          {scope==='ga' && <GA4View accountId={accountId}/>}
          {scope==='media' && <MediaPlanView accountId={accountId} currentUser={currentUser} canManage={canMediaplan} pushAudit={pushAudit}/>}
          {scope==='settings' && <SettingsView accountId={accountId} settings={g.moduleSettings} onChange={g.setModuleSettings} canManage={canSettings} currentUser={currentUser}/>}
         </div>
        </main>
      </div>

      {/* overlays */}
      <CustomColumnBuilder open={showColumns} onClose={()=>setShowColumns(false)} onSave={(col)=>setCustomCols(a=>[...a,col])}/>
      <AutomationsDrawer open={showAutomations} onClose={()=>setShowAutomations(false)} rules={rules} setRules={setRules}/>
      <CommandPalette open={showPalette} onClose={()=>setShowPalette(false)} accountId={accountId} platformId={scope.startsWith('platform:')?scope.split(':')[1]:'overview'}
        onAction={(it)=>{ switch(it.action){
          case 'go-platform': g.setScope(it.payload==='overview'?'overview':`platform:${it.payload}`); break;
          case 'toggle-dark': setDark(d=>!d); break;
          case 'open-reallocator': setShowReallocator(true); break;
          case 'open-automations': setShowAutomations(true); break;
          case 'open-columns': setShowColumns(true); break;
          case 'mark-read': markAllRead(); break;
          case 'view-campaign': g.setScope(`platform:${it.payload.platform}`); g.setSearch(it.payload.name); break;
          case 'view-adset': g.setScope(`platform:${it.payload.campaign.platform}`); g.setSearch(it.payload.adset.name); break;
          default: break;
        } }}/>
      <ReallocatorModal open={showReallocator} onClose={()=>setShowReallocator(false)} accountId={accountId}/>
      <ToastStack toasts={toasts} onDismiss={dismissToast}/>
    </div>
  );
}

/* FreshnessChips lives here (uses platform feeds) */
function FreshnessChips(){
  const { feeds } = useGlobal();
  useDataVersion();                                  // re-render when freshness loads
  const [, tick] = useState(0);
  useEffect(()=>{ const t=setInterval(()=>tick(x=>x+1),3500); return ()=>clearInterval(t); }, []);
  const fresh = platformFreshness();
  const fmtLag = (s)=> s<60?`${s}s`:`${Math.floor(s/60)}:${String(s%60).padStart(2,'0')}`;
  const plats = PLATFORMS.filter(p=>p.id!=='overview' && p.id!=='google_analytics' && feeds[p.id]);
  return (
    <div className="flex items-center gap-1.5 text-[11px] font-mono overflow-x-auto scroll-none">
      <span className="inline-flex items-center gap-1 text-ink-500 dark:text-ink-300"><LiveDot tone={plats.length?'#10b981':'#8b8b80'} size={6}/>Feeds</span>
      <span className="text-ink-300 dark:text-ink-500">·</span>
      {plats.length===0 && <span className="text-ink-400">no live feeds — connect a source in Admin</span>}
      {plats.map(p=>{
        const f=fresh[p.id]||{lag:0,status:'ok'}; const delayed=f.status==='delayed';
        return (<span key={p.id} title={`${p.label}: ${fmtLag(f.lag)}`} className={`inline-flex items-center gap-1 px-1.5 h-5 rounded ${delayed?'bg-rose-50 text-rose-700 dark:bg-rose-500/15 dark:text-rose-300':'text-ink-500 dark:text-ink-300 hover:bg-ink-100 dark:hover:bg-white/5'}`}>
          <span className="inline-flex items-center justify-center w-3.5 h-3.5 text-ink-900 dark:text-white"><BrandIcon name={p.icon} size={13}/></span><span className="tabular">{fmtLag(f.lag)}</span>{delayed&&<span className="text-[9px] font-bold uppercase ml-0.5">late</span>}</span>);
      })}
    </div>
  );
}

Object.assign(window, { GlobalContext, useGlobal, GlobalProvider, Workspace, Sidebar, OverviewView, FreshnessChips, AccountSwitcher, DateRangePicker, DATE_PRESETS });
/* v4 — manual Meta refresh button added 2026-07-02 */
