/* Integrations / data wiring manager ================================
   Lives in the Admin Panel. Connections feed the dashboard through one
   of three paths — MCP gateway, direct platform API, or manual import —
   plus the MySQL persistence store. All actions hit the real backend.
=================================================================== */

const KIND_META = {
  mcp:    { label:'MCP gateway',    tag:'MCP',    blurb:'JSON-RPC to an MCP server that streams platform data.' },
  api:    { label:'Direct · API',   tag:'API',    blurb:'Authenticated REST pull from the platform (or a proxy).' },
  manual: { label:'Manual import',  tag:'MANUAL', blurb:'Upload CSV / spreadsheet exports — no live connection.' },
  db:     { label:'Data store',     tag:'SQL',    blurb:'The persistence layer (users, audit, saved views).' },
};

/* Templates for the "New connection" menu.
   Zernio (Late) is the unified MCP connector — one connection feeds Meta,
   TikTok, X and LinkedIn. It replaces the old Pipeboard MCP path for TikTok + X.
   NOTE: Google is intentionally NOT on Zernio — Zernio's unified tree returns 0
   for Google, so Google Ads stays on its own native Google Ads MCP connection.
   The direct per-platform API presets remain as fallbacks. */
const CONN_PRESETS = [
  { id:'zernio',   name:'Zernio — unified ads (MCP)', kind:'mcp', provider:'zernio', tone:'#8351ff', platforms:['meta','tiktok','x','linkedin'], endpoint:'mcp://api.zernio.co/v1/stream', scopes:['ads.read','insights.read'], config:{ sync_tool:'get_ads_bundle' } },
  { id:'google',   name:'Google Ads (MCP)',   kind:'mcp', provider:'google',    tone:'#34A853', platforms:['google'], endpoint:'mcp://ads.google.com/mcp/v1', scopes:['adwords'], config:{ sync_tool:'get_google_ads_bundle' } },
  { id:'meta',     name:'Meta Ads',          kind:'api', provider:'meta',      tone:'#2f7bff', platforms:['meta','facebook','instagram'], endpoint:'https://graph.facebook.com/v19.0', scopes:['ads_read'] },
  { id:'tiktok',   name:'TikTok Ads',        kind:'api', provider:'tiktok',    tone:'#06b6d4', platforms:['tiktok'], endpoint:'https://business-api.tiktok.com/open_api/v1.3', scopes:['ad.read'] },
  { id:'snapchat', name:'Snapchat Ads',      kind:'api', provider:'snapchat',  tone:'#eab308', platforms:['snapchat'], endpoint:'https://adsapi.snapchat.com/v1', scopes:['snapchat-marketing-api'] },
  { id:'x',        name:'X / Twitter Ads',   kind:'api', provider:'x',         tone:'#ec4899', platforms:['x'], endpoint:'https://ads-api.x.com/12', scopes:['ads.read'] },
  { id:'linkedin', name:'LinkedIn Ads',      kind:'api', provider:'linkedin',  tone:'#0A66C2', platforms:['linkedin'], endpoint:'https://api.linkedin.com/rest/adAccounts', scopes:['r_ads_reporting'] },
  { id:'custom',   name:'Custom MCP endpoint',kind:'mcp',provider:'custom',    tone:'#5e5e55', platforms:[], endpoint:'', scopes:[] },
  { id:'manual',   name:'Manual import',     kind:'manual', provider:'manual', tone:'#10b981', platforms:[], endpoint:'', scopes:[] },
  { id:'mysql',    name:'MySQL — Hostinger',  kind:'db', provider:'mysql',     tone:'#10b981', platforms:[], endpoint:'mysql://localhost:3306', scopes:[] },
];

function healthMeta(i){
  if (i.status !== 'connected') return { tone:'#8b8b80', label:'Disconnected', dot:'#8b8b80' };
  if (i.health === 'degraded')  return { tone:'#f59e0b', label:'Degraded',     dot:'#f59e0b' };
  return { tone:'#10b981', label:'Healthy', dot:'#10b981' };
}
function maskToken(t){
  if (!t) return '—';
  if (t.length <= 8) return '••••••••';
  return t.slice(0,4) + '••••••••' + t.slice(-4);
}
function agoStr(ts){
  if (!ts) return 'never';
  const s = Math.floor((Date.now()-ts)/1000);
  if (s<60) return s+'s ago';
  if (s<3600) return Math.floor(s/60)+'m '+(s%60)+'s ago';
  return Math.floor(s/3600)+'h ago';
}

const CSV_TEMPLATE = 'platform,campaign_id,campaign_name,status,budget,date,spend,impressions,clicks,conversions,revenue\n'
  + 'meta,1001,Prospecting — Advantage+,active,500,2026-06-01,420,58000,1180,42,1680\n'
  + 'google,2001,Brand Search — Exact,active,300,2026-06-01,280,12000,640,55,2100\n';

/* ---------- Connection detail drawer ------------------------------- */
function ConnectionDrawer({ open, integration, onClose, onUpdate, onDelete, readOnly }){
  const [draft, setDraft] = useState(integration||{});
  const [showTok, setShowTok] = useState(false);
  const [log, setLog] = useState([]);
  const [busy, setBusy] = useState(false);
  const [csv, setCsv] = useState('');
  const [importAcc, setImportAcc] = useState('');
  const [importMsg, setImportMsg] = useState('');
  const logRef = useRef(null);
  const fileRef = useRef(null);

  useEffect(()=>{ if(open){ setDraft({...integration}); setShowTok(false); setLog([]); setBusy(false); setCsv(''); setImportMsg('');
    const accs = integration && integration.accounts;
    const first = (accs==='*'||(Array.isArray(accs)&&accs.includes('*'))) ? (ACCOUNTS[0]&&ACCOUNTS[0].id) : (Array.isArray(accs)&&accs[0]) || (ACCOUNTS[0]&&ACCOUNTS[0].id);
    setImportAcc(first||'');
  } }, [open, integration]);
  useEffect(()=>{ if(logRef.current) logRef.current.scrollTop = logRef.current.scrollHeight; }, [log]);
  if (!integration) return null;

  const set = (k,v)=>setDraft(d=>({...d,[k]:v}));
  const setCfg = (k,v)=>setDraft(d=>({...d, config:{...(d.config||{}), [k]:v}}));
  const h = healthMeta(draft);
  const kind = draft.kind;
  const isDb = kind==='db', isMcp = kind==='mcp', isApi = kind==='api', isManual = kind==='manual';
  const cfg = draft.config || {};

  /* Animate a returned log array line-by-line for the terminal feel. */
  const playLog = (lines) => new Promise(res=>{
    setLog([]); let i=0;
    const tick = ()=>{ if(i>=lines.length){ res(); return; } setLog(l=>[...l, lines[i]]); i++; setTimeout(tick, 220+Math.random()*180); };
    tick();
  });

  const runTest = async () => {
    if (busy) return; setBusy(true);
    try { const lines = await RelayAPI.integrations.test(draft.id); await playLog(lines); }
    catch(e){ setLog([{line:'✗ '+(e.message||'test failed'), tone:'err'}]); }
    setBusy(false);
  };

  const toggleConnect = async () => {
    if (busy) return; setBusy(true);
    try {
      if (draft.status==='connected'){
        const saved = await onUpdate(draft.id, { status:'disconnected', health:'offline', lastSync:null });
        setDraft(d=>({...d, ...saved}));
        setLog([{line:'→ closing connection…',tone:''},{line:'✓ disconnected',tone:'ok'}]);
      } else {
        // Persist current config first, then connect, then (mcp/api) sync.
        const saved = await onUpdate(draft.id, { ...draft, status:'connected', health:'healthy', lastSync:Date.now() });
        setDraft(d=>({...d, ...saved}));
        if (isMcp || isApi){
          await playLog([{line:'→ establishing '+(isMcp?'MCP stream':'API session')+'…',tone:''},{line:'✓ connected',tone:'ok'},{line:'→ running first sync…',tone:''}]);
          try { const r = await RelayAPI.integrations.sync(draft.id);
            if (r && r.note) setLog(l=>[...l,{line:'· '+r.note,tone:''}]);
            else setLog(l=>[...l,{line:`✓ sync complete · ${r.campaigns||0} campaigns · ${r.metrics||0} metric rows`,tone:'ok'}]);
          } catch(e){ setLog(l=>[...l,{line:'✗ sync error: '+(e.message||''),tone:'err'}]); }
        } else {
          setLog([{line:'✓ connected',tone:'ok'}]);
        }
      }
    } catch(e){ setLog([{line:'✗ '+(e.message||'failed'),tone:'err'}]); }
    setBusy(false);
  };

  const save = async () => {
    if (busy) return; setBusy(true);
    /* status/health/lastSync are managed by Connect/Disconnect — don't resend on a plain save. */
    const { status, health, lastSync, ...rest } = draft;
    try { const saved = await onUpdate(draft.id, rest); setDraft(d=>({...d,...saved})); onClose(); }
    catch(e){ setLog([{line:'✗ '+(e.message||'save failed'),tone:'err'}]); }
    setBusy(false);
  };

  const onFile = (file) => { if(!file) return; const r=new FileReader(); r.onload=e=>setCsv(String(e.target.result||'')); r.readAsText(file); };
  const runImport = async () => {
    if (busy || !csv.trim()) return; setBusy(true); setImportMsg('');
    try {
      const r = await RelayAPI.ingest({ account: importAcc, integration: draft.id, csv });
      const c = r.imported||{};
      setImportMsg(`Imported ${c.campaigns||0} campaigns · ${c.metrics||0} metric rows.`);
      await onUpdate(draft.id, { status:'connected', health:'healthy', lastSync:Date.now() });
    } catch(e){ setImportMsg('✗ '+(e.message||'import failed')); }
    setBusy(false);
  };
  const downloadTemplate = () => {
    const a=document.createElement('a');
    a.href='data:text/csv;charset=utf-8,'+encodeURIComponent(CSV_TEMPLATE);
    a.download='relay-import-template.csv'; a.click();
  };

  const importAccounts = (draft.accounts==='*'||(Array.isArray(draft.accounts)&&draft.accounts.includes('*'))) ? ACCOUNTS : ACCOUNTS.filter(a=>(draft.accounts||[]).includes(a.id));

  return (
    <Drawer open={open} onClose={onClose} width={540}
      title={<><span className="inline-flex items-center justify-center w-6 h-6 text-ink-900 dark:text-white"><BrandIcon name={PROVIDER_ICON[draft.provider]||'custom'} size={22}/></span> {draft.name}</>}
      footer={
        <>
          <span className="mr-auto inline-flex items-center gap-1.5 text-[12px] font-medium" style={{ color:h.tone }}>
            <span className="w-2 h-2 rounded-full" style={{ background:h.dot }}/> {h.label}
          </span>
          {!readOnly && <Btn variant="ghost" icon="x" onClick={()=>{ if(confirm('Remove this connection?')){ onDelete(draft.id); onClose(); } }}>Remove</Btn>}
          <Btn variant="ghost" onClick={onClose}>Close</Btn>
          {!readOnly && <Btn variant="accent" icon="check" onClick={save} disabled={busy}>Save connection</Btn>}
        </>
      }>
      <div className="p-5 space-y-5">
        {/* status row */}
        <div className="flex items-center gap-3 p-3 rounded-xl border border-ink-200 dark:border-white/10 bg-ink-50/60 dark:bg-white/[0.02]">
          <div className="flex-1">
            <div className="text-[11px] text-ink-500 dark:text-ink-300">{KIND_META[kind]?.label}</div>
            <div className="text-[13px] font-medium mt-0.5">Last sync · <span className="font-mono">{agoStr(draft.lastSync)}</span></div>
          </div>
          {!readOnly && !isManual && (
            <Btn variant={draft.status==='connected'?'ghost':'accent'} icon={draft.status==='connected'?'link-break':'zap'} onClick={toggleConnect} disabled={busy}>
              {busy ? 'Working…' : draft.status==='connected' ? 'Disconnect' : 'Connect'}
            </Btn>
          )}
        </div>

        <Field label="Connection name">
          <input value={draft.name||''} disabled={readOnly} onChange={e=>set('name',e.target.value)} className={inputCls}/>
        </Field>

        {!isManual && (
          <Field label={isDb?'Host':'Endpoint URL'}>
            <input value={draft.endpoint||''} disabled={readOnly} onChange={e=>set('endpoint',e.target.value)}
              placeholder={isMcp?'mcp://your-server.com/v1/stream':isDb?'mysql://host:3306':'https://…'} className={inputCls+' font-mono text-[12px]'}/>
          </Field>
        )}

        {isDb && (
          <div className="grid grid-cols-2 gap-3">
            <Field label="Database"><input value={draft.dbName||''} disabled={readOnly} onChange={e=>set('dbName',e.target.value)} className={inputCls+' font-mono text-[12px]'}/></Field>
            <Field label="User"><input value={draft.dbUser||''} disabled={readOnly} onChange={e=>set('dbUser',e.target.value)} className={inputCls+' font-mono text-[12px]'}/></Field>
          </div>
        )}

        {/* token (not for manual) */}
        {!isManual && (
          <Field label={isDb?'Password':'Access token / API key'} hint={readOnly?'read-only':'encrypted at rest (AES-256)'}>
            <div className="relative">
              <input type={showTok?'text':'password'} value={draft.token||''} disabled={readOnly} onChange={e=>set('token',e.target.value)}
                placeholder="paste token" className={inputCls+' pr-11 font-mono text-[12px]'}/>
              <button type="button" onClick={()=>setShowTok(s=>!s)} className="absolute right-1.5 top-1/2 -translate-y-1/2 h-8 w-8 grid place-items-center rounded-lg text-ink-400 hover:bg-ink-100 dark:hover:bg-white/10">
                <Icon name="eye" size={15}/>
              </button>
            </div>
          </Field>
        )}

        {/* MCP-specific: tool that returns the data bundle */}
        {isMcp && (
          <Field label="Sync tool" hint="MCP tool name that returns the data bundle">
            <input value={cfg.sync_tool||''} disabled={readOnly} onChange={e=>setCfg('sync_tool', e.target.value)}
              placeholder="e.g. get_insights" className={inputCls+' font-mono text-[12px]'}/>
          </Field>
        )}

        {/* API-specific: insights URL returning the normalized bundle */}
        {isApi && (
          <Field label="Insights URL" hint="REST endpoint returning the data bundle ({account} placeholder)">
            <input value={cfg.insights_url||''} disabled={readOnly} onChange={e=>setCfg('insights_url', e.target.value)}
              placeholder="https://…/insights?account={account}" className={inputCls+' font-mono text-[12px]'}/>
          </Field>
        )}

        {/* platforms routed (mcp / api) */}
        {(isMcp || isApi) && (
          <Field label="Platforms this connection feeds">
            <div className="flex flex-wrap gap-1.5">
              {PLATFORMS.filter(p=>p.id!=='overview').map(p=>{
                const on = (draft.platforms||[]).includes(p.id);
                return (
                  <button key={p.id} type="button" disabled={readOnly}
                    onClick={()=>{ const cur=draft.platforms||[]; set('platforms', cur.includes(p.id)?cur.filter(x=>x!==p.id):[...cur,p.id]); }}
                    className={`inline-flex items-center gap-1.5 h-8 px-2.5 rounded-lg border text-[12px] font-medium transition
                      ${on?'border-transparent':'border-ink-200 dark:border-white/10 text-ink-500 hover:bg-ink-50 dark:hover:bg-white/5'}`}
                    style={on?{ background:`${p.tone}1f`, color:p.tone }:{}}>
                    <span className="inline-flex items-center justify-center w-4 h-4 text-ink-900 dark:text-white"><BrandIcon name={p.icon} size={14}/></span>{p.label}
                    {on && <Icon name="check" size={12}/>}
                  </button>
                );
              })}
            </div>
          </Field>
        )}

        {/* account mapping */}
        <Field label="Mapped ad accounts" hint="which accounts this feed populates">
          <AccountAccess value={draft.accounts} onChange={readOnly?()=>{}:(v=>set('accounts',v))}/>
        </Field>

        {/* sync frequency (mcp/api) */}
        {(isMcp || isApi) && (
          <Field label="Sync frequency">
            <div className="flex items-center gap-2">
              {[15,30,60,120,300].map(f=>(
                <button key={f} type="button" disabled={readOnly} onClick={()=>set('syncFreq',f)}
                  className={`h-9 px-3 rounded-lg text-[12.5px] font-mono font-medium border transition
                    ${draft.syncFreq===f?'border-accent-300 bg-accent-50 text-accent-700 dark:bg-accent-500/15 dark:border-accent-500/40 dark:text-accent-200':'border-ink-200 dark:border-white/10 hover:bg-ink-50 dark:hover:bg-white/5'}`}>
                  {f<60?f+'s':(f/60)+'m'}
                </button>
              ))}
            </div>
          </Field>
        )}

        {/* MANUAL import panel */}
        {isManual && !readOnly && (
          <div className="rounded-xl border border-ink-200 dark:border-white/10 p-3 space-y-3">
            <div className="flex items-center justify-between">
              <span className="text-[12.5px] font-semibold">Import data</span>
              <button onClick={downloadTemplate} className="text-[11.5px] text-accent-600 dark:text-accent-300 hover:underline">Download CSV template</button>
            </div>
            <Field label="Target account">
              <select value={importAcc} onChange={e=>setImportAcc(e.target.value)} className={inputCls}>
                {importAccounts.map(a=><option key={a.id} value={a.id}>{a.name}</option>)}
              </select>
            </Field>
            <input ref={fileRef} type="file" accept=".csv,text/csv" className="hidden" onChange={e=>onFile(e.target.files[0])}/>
            <div className="flex items-center gap-2">
              <Btn size="sm" variant="subtle" icon="plus" onClick={()=>fileRef.current && fileRef.current.click()}>Choose CSV…</Btn>
              <span className="text-[11px] text-ink-400 font-mono">{csv?`${csv.split(/\r?\n/).length-1} rows ready`:'no file'}</span>
            </div>
            <textarea value={csv} onChange={e=>setCsv(e.target.value)} placeholder="…or paste CSV here"
              className={inputCls+' h-24 py-2 font-mono text-[11px] leading-relaxed'} style={{height:96}}/>
            <div className="flex items-center justify-between">
              <span className="text-[11.5px] text-ink-500 dark:text-ink-300">{importMsg}</span>
              <Btn size="sm" variant="accent" icon="check" onClick={runImport} disabled={busy||!csv.trim()||!importAcc}>Import</Btn>
            </div>
          </div>
        )}

        {/* test connection (not manual) */}
        {!isManual && (
          <div>
            <div className="flex items-center justify-between mb-2">
              <span className="text-[12px] font-medium text-ink-700 dark:text-ink-200">Test connection</span>
              <Btn size="sm" variant="subtle" icon="play" onClick={runTest} disabled={busy}>{busy?'Running…':'Run test'}</Btn>
            </div>
            <div ref={logRef} className="h-36 overflow-auto scroll-thin rounded-xl bg-ink-900 dark:bg-black/40 border border-white/10 p-3 font-mono text-[11.5px] leading-relaxed">
              {log.length===0 && <div className="text-white/30">$ awaiting test run…</div>}
              {log.map((l,i)=>(
                <div key={i} className="animate-fadein" style={{ color: l.tone==='ok'?'#6ee7b7':l.tone==='err'?'#fda4af':'rgba(255,255,255,0.7)' }}>{l.line}</div>
              ))}
              {busy && <div className="text-white/40 inline-flex items-center gap-1.5"><span className="w-2.5 h-2.5 rounded-full border border-white/40 border-t-transparent animate-spin"/></div>}
            </div>
          </div>
        )}
      </div>
    </Drawer>
  );
}

/* ---------- Integration card --------------------------------------- */
function IntegrationCard({ i, onOpen }){
  const h = healthMeta(i);
  const connected = i.status==='connected';
  return (
    <button onClick={()=>onOpen(i)}
      className="group text-left relative overflow-hidden rounded-2xl border border-ink-200 dark:border-white/10 bg-white dark:bg-ink-900/60 shadow-card p-4 hover:shadow-float hover:-translate-y-0.5 transition-all">
      {i.primary && <span className="absolute top-3 right-3 text-[9.5px] font-mono uppercase tracking-wider px-1.5 py-0.5 rounded bg-accent-100 text-accent-700 dark:bg-accent-500/15 dark:text-accent-200">Primary</span>}
      <div className="flex items-start gap-3">
        <span className="inline-flex items-center justify-center w-11 h-11 rounded-xl flex-shrink-0 text-ink-900 dark:text-white" style={{ background:`${i.tone||'#8351ff'}14` }}><BrandIcon name={PROVIDER_ICON[i.provider]||'custom'} size={30}/></span>
        <div className="min-w-0 flex-1">
          <div className="text-[14px] font-semibold truncate">{i.name}</div>
          <div className="text-[10.5px] font-mono uppercase tracking-wide text-ink-400 mt-0.5">{KIND_META[i.kind]?.tag}</div>
        </div>
      </div>

      <div className="mt-3 flex items-center gap-1.5">
        {(i.platforms||[]).length>0
          ? (i.platforms||[]).map(p=>{ const pl=PLATFORMS.find(x=>x.id===p); return pl && (
              <span key={p} className="inline-flex items-center justify-center w-6 h-6 text-ink-900 dark:text-white"><BrandIcon name={pl.icon} size={18}/></span>
            ); })
          : <span className="text-[11px] text-ink-400">{i.kind==='db'?'persistence layer':i.kind==='manual'?'manual import':'no platforms routed'}</span>}
      </div>

      <div className="mt-3 pt-3 border-t border-ink-100 dark:border-white/5 flex items-center justify-between">
        <span className="inline-flex items-center gap-1.5 text-[11.5px] font-medium" style={{ color:h.tone }}>
          {connected && i.health!=='degraded'
            ? <LiveDot tone={h.dot} size={6}/>
            : <span className="w-1.5 h-1.5 rounded-full" style={{ background:h.dot }}/>}
          {h.label}
        </span>
        <span className="text-[11px] font-mono text-ink-400">{connected ? agoStr(i.lastSync) : 'offline'}</span>
      </div>
    </button>
  );
}

/* ---------- Integrations manager ----------------------------------- */
function IntegrationsManager({ integrations, setIntegrations, readOnly, currentUser, pushAudit }){
  const [open, setOpen] = useState(null);
  const [, force] = useState(0);
  useEffect(()=>{ const t=setInterval(()=>force(x=>x+1), 1000); return ()=>clearInterval(t); }, []);

  const onUpdate = async (id, patch) => {
    const saved = await RelayAPI.integrations.update(id, patch);
    setIntegrations(arr => arr.map(x=>x.id===saved.id?saved:x));
    if (pushAudit) pushAudit();
    return saved;
  };
  const onDelete = async (id) => {
    await RelayAPI.integrations.remove(id);
    setIntegrations(arr => arr.filter(x=>x.id!==id));
    if (pushAudit) pushAudit();
  };
  const onCreate = async (preset) => {
    const it = await RelayAPI.integrations.create({
      name:preset.name, kind:preset.kind, provider:preset.provider, tone:preset.tone,
      endpoint:preset.endpoint, platforms:preset.platforms, scopes:preset.scopes,
      config:preset.config||{}, accounts:[], syncFreq:60,
    });
    setIntegrations(arr => [...arr, it]);
    if (pushAudit) pushAudit();
    setOpen(it);   // open the drawer to finish configuring
  };

  const groups = [
    { key:'mcp',    title:'MCP gateways',     test:(i)=>i.kind==='mcp' },
    { key:'api',    title:'Direct platforms', test:(i)=>i.kind==='api' },
    { key:'other',  title:'Manual & data',    test:(i)=>i.kind==='manual'||i.kind==='db' },
  ];
  const feeds = connectedPlatforms(integrations);

  return (
    <div>
      <div className="flex items-center justify-between gap-3 mb-4 flex-wrap">
        <div>
          <h2 className="text-[18px] font-semibold tracking-tight">Integrations & data wiring</h2>
          <p className="text-[12.5px] text-ink-500 dark:text-ink-300">Configure every pipe feeding the dashboard. {Object.keys(feeds).length} platform feed{Object.keys(feeds).length===1?'':'s'} live.</p>
        </div>
        {!readOnly && (
          <Dropdown align="right" width={260} trigger={<Btn variant="accent" icon="plus">New connection</Btn>}>
            {(close)=>(
              <div className="py-1">
                <div className="px-2 pt-1 pb-1.5 text-[10.5px] uppercase font-semibold tracking-wide text-ink-400">Add a data source</div>
                {CONN_PRESETS.map(p=>(
                  <button key={p.id} onClick={()=>{ close(); onCreate(p); }}
                    className="w-full flex items-center gap-2.5 px-2 py-2 rounded-lg hover:bg-ink-100 dark:hover:bg-white/5 text-left">
                    <span className="inline-flex items-center justify-center w-7 h-7 rounded-lg text-ink-900 dark:text-white" style={{background:`${p.tone}18`}}><BrandIcon name={PROVIDER_ICON[p.provider]||'custom'} size={18}/></span>
                    <span className="flex-1 min-w-0"><span className="text-[12.5px] font-medium block truncate">{p.name}</span><span className="text-[10.5px] font-mono text-ink-400">{KIND_META[p.kind]?.tag}</span></span>
                  </button>
                ))}
              </div>
            )}
          </Dropdown>
        )}
      </div>

      {/* recommendation banner */}
      <div className="mb-5 rounded-2xl border border-accent-200 dark:border-accent-500/30 bg-accent-50/70 dark:bg-accent-500/[0.07] p-4 flex items-start gap-3">
        <span className="inline-flex items-center justify-center w-10 h-10 rounded-xl bg-accent-500/15 text-accent-600 dark:text-accent-300 flex-shrink-0"><RelayMark size={22} tone="#8351ff"/></span>
        <div className="flex-1">
          <div className="text-[13px] font-semibold text-accent-800 dark:text-accent-200">Three ways to bring data in</div>
          <div className="text-[12.5px] text-ink-600 dark:text-ink-300 leading-relaxed mt-0.5">
            <b>MCP</b> — point at an MCP server that streams platform insights. <b>API</b> — pull directly from a platform (or a thin proxy) that returns the data bundle. <b>Manual</b> — upload CSV exports. Each platform can use whichever path you have access to.
          </div>
        </div>
      </div>

      {integrations.length===0 && (
        <div className="rounded-2xl border border-dashed border-ink-300 dark:border-white/15 p-10 text-center">
          <div className="text-[14px] font-semibold">No connections yet</div>
          <div className="text-[12.5px] text-ink-500 dark:text-ink-300 mt-1">Click <b>New connection</b> to wire your first data source.</div>
        </div>
      )}

      <div className="space-y-6">
        {groups.map(g=>{
          const items = integrations.filter(g.test);
          if (!items.length) return null;
          return (
            <div key={g.key}>
              <div className="flex items-baseline gap-2 mb-2.5">
                <h3 className="text-[13px] font-semibold">{g.title}</h3>
              </div>
              <div className="grid grid-cols-2 lg:grid-cols-3 gap-3">
                {items.map(i=> <IntegrationCard key={i.id} i={i} onOpen={setOpen}/>)}
              </div>
            </div>
          );
        })}
      </div>

      <ConnectionDrawer open={!!open} integration={open} onClose={()=>setOpen(null)}
        onUpdate={onUpdate} onDelete={onDelete} readOnly={readOnly}/>
    </div>
  );
}

Object.assign(window, { IntegrationsManager, ConnectionDrawer, IntegrationCard, healthMeta, maskToken, agoStr });
