/* Campaign Table with nested Campaign → AdSet → Offer drilldown ===== */

const DEFAULT_COLS = [
  { id:'name',    label:'Campaign',         w:'minmax(280px,1.6fr)', align:'left',  sortable:true },
  { id:'status',  label:'Status',           w:'110px',               align:'left',  sortable:true },
  { id:'platform',label:'Platform',         w:'90px',                align:'left',  sortable:true },
  { id:'budget',  label:'Budget',           w:'120px',               align:'right', sortable:true, fmt:'currency' },
  { id:'spend',   label:'Spend · 7d',       w:'140px',               align:'right', sortable:true, fmt:'currency' },
  { id:'cpa',     label:'CPA · 7d',         w:'110px',               align:'right', sortable:true, fmt:'currency2' },
  { id:'roas',    label:'ROAS · 95% CI',    w:'110px',               align:'right', sortable:true, fmt:'x' },
  { id:'cpc',     label:'CPC · 7d',         w:'100px',               align:'right', sortable:true, fmt:'currency2' },
  { id:'ctr',     label:'CTR · 7d',         w:'100px',               align:'right', sortable:true, fmt:'pct' },
  { id:'conv',    label:'Conv · 7d',        w:'110px',               align:'right', sortable:true, fmt:'int' },
  { id:'pacing',  label:'Pacing',           w:'130px',               align:'left',  sortable:true },
];

/* Grid template — ROAS column drops entirely for blocklisted accounts
   (e.g. Al Munawarah). Header + campaign row + ad-set row share this. */
const _GRID_FULL   = 'minmax(220px,1.6fr) 104px 86px 112px 132px 104px 104px 96px 96px 104px 120px';
const _GRID_NOROAS = 'minmax(220px,1.6fr) 104px 86px 112px 132px 104px 96px 96px 104px 120px';
const roasHidden  = ()=> typeof metricHiddenHere === 'function' && metricHiddenHere('roas');
const campaignGrid = ()=> roasHidden() ? _GRID_NOROAS : _GRID_FULL;

/* Inline tiny sparkline (used inside table cells) */
function MicroSpark({ data, tone, width=36, height=14 }){
  if (!data || !data.length) return null;
  const vals = data.map(d=>d.v);
  const min = Math.min(...vals), max = Math.max(...vals);
  const x = i => (i*(width-2)/(data.length-1)) + 1;
  const y = v => height - 1 - ((v-min)/((max-min)||1))*(height-2);
  const path = data.map((d,i)=>(i===0?'M':'L')+x(i).toFixed(2)+','+y(d.v).toFixed(2)).join(' ');
  return (
    <svg width={width} height={height} className="inline-block flex-shrink-0">
      <path d={path} fill="none" stroke={tone} strokeWidth="1.2" strokeLinecap="round" strokeLinejoin="round" strokeOpacity="0.85"/>
    </svg>
  );
}

/* Numeric cell with optional sparkline */
function NumCell({ value, sparkData, tone='#8b8b80', className='', children }){
  return (
    <div className={`flex items-center justify-end gap-1.5 ${className}`}>
      <span className="tabular font-mono">{children ?? value}</span>
      {sparkData && <MicroSpark data={sparkData} tone={tone}/>}
    </div>
  );
}

/* ROAS cell with CI bar (small low-confidence indicator) */
function RoasCell({ roas, conv, target=1.5 }){
  const ci = roasCI(roas || 0, conv || 0);
  const r = roas || 0;
  return (
    <div className="flex items-center justify-end gap-1.5 group/roas relative">
      <span className={`tabular font-mono font-semibold ${r>=3?'text-emerald-600 dark:text-emerald-400':r<2?'text-rose-600 dark:text-rose-400':''}`}>
        {r.toFixed(2)}×
      </span>
      {ci.wide && (
        <span title={`Wide CI · only ${conv} conversions`} className="inline-flex items-center justify-center w-3.5 h-3.5 rounded-full bg-amber-100 dark:bg-amber-500/20 text-amber-700 dark:text-amber-300 text-[8px] font-bold">!</span>
      )}
      {/* hover CI bar */}
      <div className="absolute right-0 -bottom-1 translate-y-full hidden group-hover/roas:flex z-10 flex-col items-end">
        <div className="bg-ink-900 text-white text-[10px] font-mono px-2 py-1 rounded shadow-float whitespace-nowrap">
          95% CI: {ci.lo.toFixed(2)}× – {ci.hi.toFixed(2)}× <span className="opacity-60">· n={conv}</span>
        </div>
      </div>
    </div>
  );
}

function PacingBar({ value }){
  // value: ratio of pacing (1.0 = on pace); null → no budget set
  if (value == null || Number.isNaN(value)) {
    return <span className="text-[11px] font-mono text-ink-400">—</span>;
  }
  const pct = Math.min(1.5, value);
  const ok = value <= 1.05 && value >= 0.85;
  const over = value > 1.10;
  const tone = over ? '#ef4444' : ok ? '#10b981' : '#f59e0b';
  return (
    <div className="flex items-center gap-2">
      <div className="relative w-16 h-1.5 rounded-full bg-ink-100 dark:bg-white/10 overflow-hidden">
        <div className="absolute inset-y-0 left-0 rounded-full transition-all" style={{ width: (pct/1.5*100)+'%', background:tone }}/>
        <div className="absolute top-0 bottom-0" style={{ left: (1/1.5*100)+'%', width:1, background: 'rgba(0,0,0,.3)' }}/>
      </div>
      <span className="text-[11px] tabular font-mono text-ink-500 dark:text-ink-300">{(value*100).toFixed(0)}%</span>
    </div>
  );
}

function SortHeader({ col, sort, setSort }){
  const active = sort.id===col.id;
  return (
    <button
      disabled={!col.sortable}
      onClick={()=>col.sortable && setSort({ id:col.id, dir: active ? (sort.dir==='asc'?'desc':'asc') : 'desc' })}
      className={`inline-flex items-center gap-1 text-[11px] uppercase tracking-wide font-semibold ${active?'text-ink-900 dark:text-white':'text-ink-500 dark:text-ink-300'}
        ${col.sortable?'hover:text-ink-800 dark:hover:text-white':''}`}>
      {col.label}
      {col.sortable && (
        <Icon name={active && sort.dir==='asc'?'arrow-up':'arrow-down'} size={11} className={active?'opacity-100':'opacity-30'}/>
      )}
    </button>
  );
}

function AdSetRow({ as, accent, toggleStatus, readOnly }){
  const paused = as.status === 'paused';
  return (
    <div className={`${paused?'opacity-50':''}`}>
      <div className="px-4 py-2.5 grid items-center gap-3 border-t border-ink-100 dark:border-white/5 text-[13px] bg-white/40 dark:bg-white/[0.015] hover:bg-ink-50/60 dark:hover:bg-white/[0.03] transition"
        style={{ gridTemplateColumns: campaignGrid() }}>
        <div className="flex items-center gap-2 pl-6">
          <span className="inline-flex items-center justify-center w-5 h-5 rounded text-[10px] font-mono font-bold bg-ink-100 dark:bg-white/10 text-ink-600 dark:text-ink-300">AS</span>
          <span className="text-ink-700 dark:text-ink-200">{as.name}</span>
        </div>
        <div><span className={readOnly?'pointer-events-none opacity-40':''}><Toggle checked={!paused} onChange={()=>toggleStatus(as.id)} size="sm"/></span></div>
        <div className="text-ink-500"></div>
        <div className="text-ink-500 text-right">—</div>
        <div className="text-right tabular font-mono">{fmt(as.spend,'currency')}</div>
        <div className="text-right tabular font-mono">{fmt(as.cpa,'currency2')}</div>
        {!roasHidden() && <RoasCell roas={as.roas} conv={as.conv}/>}
        <div className="text-right tabular font-mono">{fmt(as.cpc,'currency2')}</div>
        <div className="text-right tabular font-mono">{(as.ctr||0).toFixed(2)}%</div>
        <div className="text-right tabular font-mono">{(as.conv||0).toLocaleString()}</div>
        <div></div>
      </div>
    </div>
  );
}

function CampaignRow({ c, expanded, toggleExpand, toggleStatus, readOnly }){
  const paused = c.status === 'paused';
  const accent = (PLATFORMS.find(p=>p.id===c.platform)||PLATFORMS[0]).tone;
  /* No synthetic sparklines — cells show real range values only. */
  const funnel = useMemo(()=>campaignFunnel(c), [c.id, c.spend, c.conv]);

  return (
    <div className={`group border-t border-ink-200 dark:border-white/10 ${paused?'opacity-55':''}`}>
      <div className="px-4 py-3 grid items-center gap-3 hover:bg-ink-50 dark:hover:bg-white/[0.04] transition text-[13.5px]"
        style={{ gridTemplateColumns: campaignGrid() }}>
        <div className="flex items-center gap-2 sticky left-0 z-[2] bg-white dark:bg-ink-900 pl-4 -ml-4 pr-2 stick-edge group-hover:bg-ink-50 dark:group-hover:bg-[#15150e]">
          <button onClick={()=>toggleExpand(c.id)} className="h-5 w-5 rounded grid place-items-center hover:bg-ink-100 dark:hover:bg-white/10">
            <Icon name="chev-right" size={12} className={`transition-transform ${expanded?'rotate-90':''}`}/>
          </button>
          {!paused && <LiveDot tone={accent}/>}
          {paused && <span className="w-2 h-2 rounded-full bg-ink-300 dark:bg-white/20"/>}
          <span className="font-medium text-ink-900 dark:text-white">{c.name}</span>
          <span className="text-[11px] font-mono text-ink-400 dark:text-ink-400">{(()=>{
            const parts = String(c.id||'').split('_');
            return parts.length >= 2 ? parts[parts.length-2] + '-' + parts[parts.length-1] : (c.id || '');
          })()}</span>
        </div>
        <div className="flex items-center gap-2">
          <span className={readOnly?'pointer-events-none opacity-40':''}><Toggle checked={!paused} onChange={()=>toggleStatus(c.id)} size="sm"/></span>
          <Pill tone={paused?'neutral':'good'}>{paused?'Paused':'Active'}</Pill>
        </div>
        <div><PlatformChip p={c.platform}/></div>
        <div className="text-right tabular font-mono">{fmt(c.budget,'currency')}</div>
        <NumCell tone={accent}><span className="font-semibold">{fmt(c.spend,'currency')}</span></NumCell>
        <NumCell tone="#f59e0b">{fmt(c.cpa,'currency2')}</NumCell>
        {!roasHidden() && <RoasCell roas={c.roas} conv={c.conv}/>}
        <NumCell tone="#06b6d4">{fmt(c.cpc,'currency2')}</NumCell>
        <NumCell tone="#ec4899">{(c.ctr||0).toFixed(2)}%</NumCell>
        <NumCell tone="#10b981">{(c.conv||0).toLocaleString()}</NumCell>
        <div><PacingBar value={c.pacing}/></div>
      </div>
      {expanded && (
        <div className="bg-ink-50/40 dark:bg-white/[0.015] px-4 pt-3 pb-3 space-y-3">
          {/* Funnel strip */}
          <FunnelStrip steps={funnel}/>
          {/* Ad sets */}
          <div className="rounded-xl border border-ink-100 dark:border-white/5 overflow-hidden bg-white/40 dark:bg-white/[0.01]">
            <div className="px-3 py-2 text-[10.5px] uppercase font-semibold tracking-wide text-ink-500 dark:text-ink-300 border-b border-ink-100 dark:border-white/5 bg-ink-50/40 dark:bg-white/[0.02]">
              Ad sets · {(c.adsets||[]).length}
            </div>
            {(c.adsets||[]).map(as => <AdSetRow key={as.id} as={as} accent={accent} toggleStatus={toggleStatus} readOnly={readOnly}/>)}
          </div>
        </div>
      )}
    </div>
  );
}

function CampaignTable({ accountId, platformId, search='', onOpenColumns, canEdit=true }){
  const readOnly = !canEdit;
  const baseCampaigns = useMemo(()=>getCampaigns(accountId, platformId), [accountId, platformId]);

  /* Local state: status & expansion */
  const [statusMap, setStatusMap] = useState({}); // id -> 'active' | 'paused'
  useEffect(()=>{ setStatusMap({}); setExpanded({}); }, [accountId, platformId]);

  const [expanded, setExpanded] = useState({});
  const toggleExpand = (id)=> setExpanded(s => ({...s, [id]: !s[id]}));
  const toggleStatus = (id) => { if(readOnly) return; setStatusMap(s => {
    const current = s[id];
    const all = [...baseCampaigns, ...baseCampaigns.flatMap(c=>c.adsets||[])];
    const it = all.find(x => x.id===id);
    const base = it?.status;
    const isActive = current ? current === 'active' : base === 'active';
    return { ...s, [id]: isActive ? 'paused' : 'active' };
  }); };

  const applyStatus = (it) => {
    const ov = statusMap[it.id];
    return ov ? { ...it, status: ov } : it;
  };

  const campaigns = useMemo(()=>baseCampaigns.map(c=>{
    const cc = applyStatus(c);
    cc.adsets = (c.adsets||[]).map(applyStatus);
    return cc;
  }), [baseCampaigns, statusMap]);

  /* Sort */
  const [sort, setSort] = useState({ id:'spend', dir:'desc' });
  const sorted = useMemo(()=>{
    const arr = [...campaigns];
    arr.sort((a,b)=>{
      const va = a[sort.id], vb = b[sort.id];
      if (typeof va === 'string') return sort.dir==='asc' ? va.localeCompare(vb) : vb.localeCompare(va);
      return sort.dir==='asc' ? (va||0) - (vb||0) : (vb||0) - (va||0);
    });
    return arr;
  }, [campaigns, sort]);

  /* Search filter */
  const filtered = useMemo(()=>{
    if (!search.trim()) return sorted;
    const q = search.toLowerCase();
    return sorted.filter(c => (c.name||'').toLowerCase().includes(q) || (c.adsets||[]).some(a => (a.name||'').toLowerCase().includes(q)));
  }, [sorted, search]);

  /* Totals */
  const totals = useMemo(()=>{
    return filtered.reduce((t,c)=>({
      spend: t.spend + (c.spend||0),
      conv:  t.conv  + (c.conv||0),
      budget:t.budget+ (c.budget||0),
    }), { spend:0, conv:0, budget:0 });
  }, [filtered]);

  return (
    <div className="rounded-xl border border-ink-200 dark:border-white/10 bg-white dark:bg-ink-900/60 overflow-hidden">
      {/* Header bar */}
      <div className="px-4 h-12 flex items-center justify-between border-b border-ink-200 dark:border-white/10">
        <div className="flex items-center gap-3">
          <div className="text-[13px] font-semibold">Campaigns</div>
          <Pill tone="neutral">{filtered.length} of {baseCampaigns.length}</Pill>
          <span className="text-[12px] text-ink-500 dark:text-ink-300">
            Spend <span className="font-mono tabular text-ink-800 dark:text-ink-100">{fmt(totals.spend,'currency')}</span>
            <span className="mx-2 text-ink-300">·</span>
            Conv. <span className="font-mono tabular text-ink-800 dark:text-ink-100">{totals.conv.toLocaleString()}</span>
          </span>
        </div>
        <div className="flex items-center gap-2">
          <Btn size="sm" variant="ghost" icon="filter">Filters</Btn>
          <Btn size="sm" variant="ghost" icon="columns" onClick={onOpenColumns}>Columns</Btn>
          <Btn size="sm" variant="primary" icon="plus">New campaign</Btn>
        </div>
      </div>
      {/* Column headers + body share ONE horizontal scroll container so columns stay aligned */}
      <div className="overflow-x-auto scroll-soft">
        <div style={{ minWidth: 1180 }}>
          <div className="px-4 h-10 grid items-center gap-3 border-b border-ink-200 dark:border-white/10 bg-ink-50/60 dark:bg-white/[0.02]"
            style={{ gridTemplateColumns: campaignGrid() }}>
            {DEFAULT_COLS.filter(col => !(col.id==='roas' && roasHidden())).map(col => (
              <div key={col.id} className={`${col.align==='right'?'text-right':''} ${col.id==='name'?'sticky left-0 z-[3] bg-ink-50 dark:bg-[#16160f] pl-4 -ml-4 stick-edge h-10 flex items-center':''}`}>
                <SortHeader col={col} sort={sort} setSort={setSort}/>
              </div>
            ))}
          </div>
          {/* Body */}
          <div className="max-h-[560px] overflow-y-auto scroll-soft">
            {filtered.length === 0 && (
              <div className="px-4 py-16 text-center text-ink-500 dark:text-ink-300 text-[13px]">
                {baseCampaigns.length === 0
                  ? <>No campaigns yet — connect a data source or import data in <span className="font-mono">Admin → Integrations</span>.</>
                  : <>No campaigns match <span className="font-mono">"{search}"</span></>}
              </div>
            )}
            {filtered.map(c => (
              <CampaignRow
                key={c.id}
                c={c}
                expanded={!!expanded[c.id]}
                toggleExpand={toggleExpand}
                toggleStatus={toggleStatus}
                readOnly={readOnly}
              />
            ))}
          </div>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { CampaignTable, MicroSpark, RoasCell, NumCell });
