// Overview tab — 4 sectioned sub-tabs each populated with reusable SegmentChart cards

function KPI({ label, value, foot, accent }) {
  return (
    <div className={`kpi ${accent ? 'accent-'+accent : ''}`}>
      <div className="kpi-label">{label}</div>
      <div className="kpi-value">{value}</div>
      {foot && <div className="kpi-foot">{foot}</div>}
    </div>
  );
}

function ProfitPill({ value }) {
  const cls = value > 0.5 ? 'good' : value > 0.1 ? 'ok' : 'bad';
  const sign = value > 0 ? '+' : '';
  return <span className={`seg-profit-pill ${cls}`}>{sign}{(value*100).toFixed(1)}%</span>;
}

// Shared icon-button view toggle (matches SegmentChart's toggle exactly)
function ViewToggle({ view, setView }) {
  return (
    <div className="view-toggle" title={view === 'chart' ? 'Switch to table' : 'Switch to chart'}>
      <button className={view === 'chart' ? 'active' : ''} onClick={() => setView('chart')} aria-label="Chart view">
        <svg width="14" height="14" viewBox="0 0 14 14" fill="none">
          <rect x="1" y="8" width="2.5" height="5" fill="currentColor"/>
          <rect x="5.75" y="4" width="2.5" height="9" fill="currentColor"/>
          <rect x="10.5" y="6" width="2.5" height="7" fill="currentColor"/>
        </svg>
      </button>
      <button className={view === 'table' ? 'active' : ''} onClick={() => setView('table')} aria-label="Table view">
        <svg width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="currentColor" strokeWidth="1.4">
          <rect x="1" y="2" width="12" height="10" rx="1"/>
          <line x1="1" y1="6" x2="13" y2="6"/>
          <line x1="5" y1="2" x2="5" y2="12"/>
        </svg>
      </button>
    </div>
  );
}

// ============================================================================
// SECTION 1: COMPOSITION
// ============================================================================
function CompositionSection({ data, onSelect }) {
  const segs = data.segments;
  const blendedProfit = segs.reduce((s,x) => s + x.profitPct * x.revenue, 0) / Math.max(1, data.totalRevenue);
  return (
    <div className="section-grid">
      <div className="grid grid-4 composition-kpis">
        <KPI accent="navy" label="Total guests" value={fmt.num2(data.totalUsers)} />
        <KPI accent="red" label="Total revenue (IDR)" value={fmt.idr2(data.totalRevenue)} />
        <KPI accent="gold" label="Avg revenue / guest (IDR)" value={fmt.idr2(data.totalRevenue / data.totalUsers)}
             foot={<>Across all active segments</>} />
        <KPI accent="navy" label="Blended profit margin" value={fmt.pct(blendedProfit, 2)}
             foot={<>Weighted by segment revenue</>} />
      </div>

      <SegmentChart
        title="Segment size"
        subtitle="Toggle the metric to compare cohort size, revenue contribution, revenue per guest, or profit margin."
        segments={segs}
        defaultView="chart"
        metrics={[
          { key: 'userCount', label: 'Guests',                value: s => s.userCount, format: 'num' },
          { key: 'revenue',   label: 'Revenue (IDR)',         value: s => s.revenue,   format: 'idr' },
          { key: 'avgRev',    label: 'Avg rev / guest (IDR)', value: s => s.avgRev,    format: 'idr' },
          { key: 'profitPct', label: 'Profit %',              value: s => s.profitPct, format: 'pct' },
        ]}
        onSelect={onSelect}
        totalFn={(ss) => `${fmt.num2(ss.reduce((a,b)=>a+b.userCount,0))} guests · ${fmt.idr2(ss.reduce((a,b)=>a+b.revenue,0))} revenue`}
      />

      <div className="card seg-col-card">
        <div className="card-head">
          <div>
            <div className="card-title">Segment composition table</div>
            <div className="card-sub">Full numeric grid</div>
          </div>
        </div>
        <CompositionTable segments={segs} onSelect={onSelect} />
      </div>

      <SegmentChart
        title="Wallet balances"
        subtitle="Cummulative Balance vs current closing balance across each cohort's wallet."
        segments={segs}
        metrics={[
          { key: 'pctUsers',   label: 'Guest %',                   value: s => s.pctUsers,   format: 'pct', grandTotal: fmt.num(data.totalUsers), width: '20%' },
          { key: 'revPct',     label: 'Revenue %',                 value: s => s.revPct,     format: 'pct', grandTotal: fmt.idr(data.totalRevenue), width: '20%' },
          { key: 'cummBal',        label: 'Cummulative Balance (IDR)', value: s => s.cummBal,        format: 'idr', width: '16%' },
          { key: 'totalCashBal',   label: 'Total_Cash_Balance',        value: s => s.totalCashBalance,   format: 'idr', width: '16%' },
          { key: 'totalBonusBal',  label: 'Total_Bonus_Balance',       value: s => s.totalBonusBalance,  format: 'idr', width: '16%' },
          { key: 'closingBal',     label: 'Closing balance (IDR)',     value: s => s.closingBal,     format: 'idr', width: '16%' },
        ]}
        onSelect={onSelect}
        totalFn={(ss) => `Closing balance: ${fmt.idr2(ss.reduce((a,b)=>a+b.closingBal,0))}`}
      showGrandTotal={true}
      />
    </div>
  );
}

// Inline stacked bar for Liab / Redempt % of TixWon×30
function LiabRedemptBar({ liabPct, redemptPct, scaleMax, bold }) {
  const TEAL   = '#2a7286';
  const ORANGE = '#e8722a';
  const GRAY   = '#d1d5db';
  const BAR_W  = 180;
  const BAR_H  = 18;

  const toW = (pct) => (pct / scaleMax) * BAR_W;
  const w100 = toW(100);
  const wLiab = toW(liabPct);
  const wRed  = toW(redemptPct);

  const liabRound = Math.round(liabPct);
  const redRound  = Math.round(redemptPct);
  const showLiabIn = liabRound >= 10;
  const showRedIn  = redRound >= 10;

  const fontBase = { fontSize: '0.6rem', fontWeight: bold ? 700 : 600, fontFamily: "'JetBrains Mono', monospace", lineHeight: BAR_H + 'px' };

  return (
    <div style={{ display: 'inline-flex', alignItems: 'center', gap: 0 }}>
      <div style={{ position: 'relative', width: BAR_W, height: BAR_H }}>
        {/* 100% baseline */}
        <div style={{ position: 'absolute', left: 0, top: 0, width: w100, height: BAR_H, background: GRAY, borderRadius: 3, opacity: 0.25 }} />
        {/* Liability */}
        {liabRound > 0 && (
          <div style={{ position: 'absolute', left: 0, top: 0, width: Math.max(wLiab, 3), height: BAR_H, background: TEAL, borderRadius: '3px 0 0 3px', zIndex: 2, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
            {showLiabIn && <span style={{ ...fontBase, color: '#fff' }}>{liabRound}%</span>}
          </div>
        )}
        {/* Redemption stacked after */}
        {redRound > 0 && (
          <div style={{ position: 'absolute', left: wLiab, top: 0, width: Math.max(wRed, 3), height: BAR_H, background: ORANGE, borderRadius: '0 3px 3px 0', zIndex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
            {showRedIn && <span style={{ ...fontBase, color: '#fff' }}>{redRound}%</span>}
          </div>
        )}
        {/* Outside labels for small bars */}
        {liabRound > 0 && !showLiabIn && (
          <span style={{ position: 'absolute', left: Math.max(wLiab, 3) + 2, top: 0, ...fontBase, color: TEAL }}>{liabRound}%</span>
        )}
        {redRound > 0 && !showRedIn && (
          <span style={{ position: 'absolute', left: wLiab + Math.max(wRed, 3) + 2, top: 0, ...fontBase, color: ORANGE }}>{redRound}%</span>
        )}
      </div>
    </div>
  );
}

function CompositionTable({ segments }) {
  const totalUsers = segments.reduce((sum, s) => sum + s.userCount, 0);
  const totalRev = segments.reduce((sum, s) => sum + s.revenue, 0);
  const totalRed = segments.reduce((sum, s) => sum + (s.redemptionAmt || 0), 0);
  const totalVend = segments.reduce((sum, s) => sum + (s.vendingCost || 0), 0);
  const totalGp1 = totalRev - (totalRed + totalVend);
  const totalLiab = segments.reduce((sum, s) => sum + (s.liability || 0), 0);
  const totalGp2 = totalGp1 - totalLiab;

  const fmtrs = React.useMemo(() => {
    const segs = segments || [];
    return {
      userCount: fmt.columnFormatter(segs.map(s => s.userCount), 'int'),
      revenue: fmt.columnFormatter(segs.map(s => s.revenue), 'idr'),
      redemption: fmt.columnFormatter(segs.map(s => s.redemptionAmt || 0), 'idr'),
      vending: fmt.columnFormatter(segs.map(s => s.vendingCost || 0), 'idr'),
      gp1: fmt.columnFormatter(segs.map(s => s.revenue - ((s.redemptionAmt || 0) + (s.vendingCost || 0))), 'idr'),
      liability: fmt.columnFormatter(segs.map(s => s.liability || 0), 'idr'),
      gp2: fmt.columnFormatter(segs.map(s => s.revenue - ((s.redemptionAmt || 0) + (s.vendingCost || 0)) - (s.liability || 0)), 'idr'),
    };
  }, [segments]);

  const fInt = (v) => fmtrs.userCount ? fmtrs.userCount(v) : fmt.int(v);
  const fRev = (v) => fmtrs.revenue ? fmtrs.revenue(v) : fmt.idr(v);
  const fRed = (v) => fmtrs.redemption ? fmtrs.redemption(v) : fmt.idr(v);
  const fVend = (v) => fmtrs.vending ? fmtrs.vending(v) : fmt.idr(v);
  const fGp1 = (v) => fmtrs.gp1 ? fmtrs.gp1(v) : fmt.idr(v);
  const fLiab = (v) => fmtrs.liability ? fmtrs.liability(v) : fmt.idr(v);
  const fGp2 = (v) => fmtrs.gp2 ? fmtrs.gp2(v) : fmt.idr(v);

  return (
    <div className="seg-chart-table-wrap" style={{ border: 'none', borderRadius: 0, padding: 0, overflowX: 'auto' }}>
      <table className="seg-chart-table" style={{ whiteSpace: 'nowrap' }}>
        <thead>
          <tr>
            <th>Segment name</th>
            <th style={{ textAlign: 'right' }}>Guests</th>
            <th style={{ textAlign: 'right' }}>Guest %</th>
            <th style={{ textAlign: 'right' }}>Revenue (IDR)</th>
            <th style={{ textAlign: 'right' }}>Revenue %</th>
            <th style={{ textAlign: 'right' }}>Redemption (IDR)</th>
            <th style={{ textAlign: 'right' }}>Vending Cost (IDR)</th>
            <th style={{ textAlign: 'right' }}>GP1 (IDR)</th>
            <th style={{ textAlign: 'right' }}>GP1%</th>
            <th style={{ textAlign: 'right' }}>Liability (IDR)</th>
            <th style={{ textAlign: 'right' }}>GP2 (IDR)</th>
            <th style={{ textAlign: 'right' }}>GP2%</th>
          </tr>
        </thead>
        <tbody>
          {(() => {
            // Pre-compute max combined % for consistent bar scale across all rows
            const allRows = segments.map(s => {
              const tv = (s.tixWon || 0) * 30;
              const lp = tv > 0 ? ((s.liability || 0) / tv) * 100 : 0;
              const rp = tv > 0 ? ((s.redemptionAmt || 0) / tv) * 100 : 0;
              return lp + rp;
            });
            const totalTixVal = segments.reduce((a,b) => a + (b.tixWon || 0), 0) * 30;
            const gtLp = totalTixVal > 0 ? (totalLiab / totalTixVal) * 100 : 0;
            const gtRp = totalTixVal > 0 ? (totalRed / totalTixVal) * 100 : 0;
            allRows.push(gtLp + gtRp);
            const scaleMax = Math.max(Math.max(...allRows), 100);

            return segments.map((s, i) => {
              const red = s.redemptionAmt || 0;
              const vend = s.vendingCost || 0;
              const gp1 = s.revenue - (red + vend);
              const gp1Pct = s.revenue > 0 ? gp1 / s.revenue : 0;
              const liab = s.liability || 0;
              const gp2 = gp1 - liab;
              const gp2Pct = s.revenue > 0 ? gp2 / s.revenue : 0;

              const ticketVal = (s.tixWon || 0) * 30;
              const liabPct = ticketVal > 0 ? (liab / ticketVal) * 100 : 0;
              const redemptPct = ticketVal > 0 ? (red / ticketVal) * 100 : 0;

              return (
                <tr key={s.key}>
                  <td style={{ backgroundColor: SEG_PASTEL_COLORS[s.key] }}>
                    <div className="seg-chart-table-name">
                      <div className="seg-chart-swatch" style={{ background: SEG_COLORS[s.key] }} />
                      <div style={{ display: 'flex', flexDirection: 'column', gap: '2px' }}>
                        <span className="seg-name" style={{ fontWeight: 600, color: '#111827' }}>{s.key}</span>
                        <span className="seg-tag" style={{ fontSize: '0.75rem', color: '#6b7280' }}>{s.tagline}</span>
                      </div>
                    </div>
                  </td>
                  <td className="num">{fInt(s.userCount)}</td>
                  <td className="num">{fmt.pct(s.pctUsers)}</td>
                  <td className="num">{fRev(s.revenue)}</td>
                  <td className="num">{fmt.pct(s.revPct)}</td>
                  <td className="num">{fRed(red)}</td>
                  <td className="num">{fVend(vend)}</td>
                  <td className="num">{fGp1(gp1)}</td>
                  <td className="num"><ProfitPill value={gp1Pct} /></td>
                  <td className="num">{fLiab(liab)}</td>
                  <td className="num">{fGp2(gp2)}</td>
                  <td className="num"><ProfitPill value={gp2Pct} /></td>
                </tr>
              );
            });
          })()}
          {(() => {
            const totalTixVal = segments.reduce((a,b) => a + (b.tixWon || 0), 0) * 30;
            const gtLiabPct = totalTixVal > 0 ? (totalLiab / totalTixVal) * 100 : 0;
            const gtRedemptPct = totalTixVal > 0 ? (totalRed / totalTixVal) * 100 : 0;

            const allRows = segments.map(s => {
              const tv = (s.tixWon || 0) * 30;
              const lp = tv > 0 ? ((s.liability || 0) / tv) * 100 : 0;
              const rp = tv > 0 ? ((s.redemptionAmt || 0) / tv) * 100 : 0;
              return lp + rp;
            });
            allRows.push(gtLiabPct + gtRedemptPct);
            const scaleMax = Math.max(Math.max(...allRows), 100);

            return (
              <tr className="grand-total-row">
                <td><strong>Grand Total</strong></td>
                <td className="num"><strong>{fInt(totalUsers)}</strong></td>
                <td className="num"><strong>100.0%</strong></td>
                <td className="num"><strong>{fRev(totalRev)}</strong></td>
                <td className="num"><strong>100.0%</strong></td>
                <td className="num"><strong>{fRed(totalRed)}</strong></td>
                <td className="num"><strong>{fVend(totalVend)}</strong></td>
                <td className="num"><strong>{fGp1(totalGp1)}</strong></td>
                <td className="num"><strong><ProfitPill value={totalRev > 0 ? totalGp1 / totalRev : 0} /></strong></td>
                <td className="num"><strong>{fLiab(totalLiab)}</strong></td>
                <td className="num"><strong>{fGp2(totalGp2)}</strong></td>
                <td className="num"><strong><ProfitPill value={totalRev > 0 ? totalGp2 / totalRev : 0} /></strong></td>
              </tr>
            );
          })()}
        </tbody>
      </table>
    </div>
  );
}

// ============================================================================
// SECTION 2: ENGAGEMENT
// ============================================================================
function EngagementSection({ data, onSelect }) {
  const segs = data.segments;
  return (
    <div className="section-grid">
      <SegmentChart
        title="Engagement Table"
        subtitle="Key engagement metrics per segment."
        segments={segs}
        metrics={[
          { key: 'pctUsers',    label: 'Guest %',            value: s => s.pctUsers,    format: 'pct',  grandTotal: fmt.num(data.totalUsers) },
          { key: 'revPct',      label: 'Revenue %',          value: s => s.revPct,      format: 'pct',  grandTotal: fmt.idr(data.totalRevenue) },
          { key: 'totalVisits', label: 'Visit',              value: s => s.totalVisits, format: 'num' },
          { key: 'visitAvg',    label: 'Avg visit',          value: s => s.visitAvg,    format: 'dec1', grandTotal: data.grandTotal ? data.grandTotal.visitAvg : null },
          { key: 'dwellAvg',    label: 'Avg dwell time',     value: s => s.dwellAvg,    format: 'mins', grandTotal: data.grandTotal ? data.grandTotal.dwellAvg : null },
          { key: 'intervalAvg', label: 'Avg visit interval', value: s => s.intervalAvg, format: 'days', grandTotal: data.grandTotal ? data.grandTotal.intervalAvg : null },
        ]}
        onSelect={onSelect}
        showTotal={false}
        showGrandTotal={true}
      />



      <SegmentChart
        title="Visit count distribution"
        subtitle="Share of guests in each visit-count bucket. Click a row to drill into the segment."
        segments={segs}
        mode="stacked"
        valuesAreRatios={true}
        leadingMetrics={[
          { key: 'pctUsers', label: 'Guest %',   value: s => s.pctUsers, format: 'pct', grandTotal: fmt.num(data.totalUsers) },
          { key: 'revPct',   label: 'Revenue %', value: s => s.revPct,   format: 'pct', grandTotal: fmt.idr(data.totalRevenue) },
        ]}
        stackKeys={SEGMENT_DATA.VISIT_BUCKETS.map((b, i) => ({
          key: b, label: b + ' visits',
          color: ['#1a2a5e','#2e4a9f','#5a76c7','#8aa0d6','#f5d616','#e63329'][i],
          value: s => (s.visitDist[i] || 0),
        }))}
        onSelect={onSelect}
        showTotalColumn={false}
        showGrandTotal={true}
        grandTotalOverride={data.grandTotal ? { pct: data.grandTotal.visitDist } : undefined}
        highlightTopN={2}
        highlightModeDefault="col"
        showHighlightToggle={true}
      />



      <SegmentChart
        title="Day-of-week visit mix"
        subtitle="Share of each cohort's visits across days of the week."
        segments={segs}
        mode="stacked"
        stackKeys={[
          { key:'mon', label:'Mon', color:'#1a2a5e', value: s => s.dow.mon },
          { key:'tue', label:'Tue', color:'#2e4a9f', value: s => s.dow.tue },
          { key:'wed', label:'Wed', color:'#5a76c7', value: s => s.dow.wed },
          { key:'thu', label:'Thu', color:'#8aa0d6', value: s => s.dow.thu },
          { key:'fri', label:'Fri', color:'#b58e00', value: s => s.dow.fri },
          { key:'sat', label:'Sat', color:'#e63329', value: s => s.dow.sat },
          { key:'sun', label:'Sun', color:'#f5d616', value: s => s.dow.sun },
        ]}
        onSelect={onSelect}
        showTotal={false}
        showUnitToggle={true}
        showGrandTotal={true}
        highlightTopN={2}
        highlightModeDefault="col"
        stackNumFormat="k"
      />



      <MonthlyTrendCard segments={segs} onSelect={onSelect} />
    </div>
  );
}

// Monthly trend — table with months + Q1-Q4 + H1, H2, H1→H2 growth; sparkline chart view
function MonthlyTrendCard({ segments, onSelect }) {
  const [view, setView] = React.useState('table');
  const [unit, setUnit] = React.useState('num'); // 'num' | 'pct' (% of segment year total)
  const [hlMode, setHlMode] = React.useState('col'); // 'col' | 'row'
  const [timeView, setTimeView] = React.useState('pattern'); // 'series' | 'pattern'

  // Pattern is Jan -> Dec
  const PATTERN_MONTHS = SEGMENT_DATA.MONTHS;
  const PATTERN_INDICES = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];

  // Series is May '25 -> Apr '26
  const SERIES_MONTHS = ["May '25", "Jun '25", "Jul '25", "Aug '25", "Sep '25", "Oct '25", "Nov '25", "Dec '25", "Jan '26", "Feb '26", "Mar '26", "Apr '26"];
  const SERIES_INDICES = [4, 5, 6, 7, 8, 9, 10, 11, 0, 1, 2, 3];

  const months = timeView === 'series' ? SERIES_MONTHS : PATTERN_MONTHS;
  const indices = timeView === 'series' ? SERIES_INDICES : PATTERN_INDICES;

  // Helper: get the mapped months array based on timeView
  const monthsOf = (s) => {
    const raw = Array.isArray(s.monthly) ? s.monthly : (s.monthly?.months || []);
    return indices.map(i => raw[i] || 0);
  };
  const yearTotal = (s) => monthsOf(s).reduce((a,b)=>a+b,0);
  const valOr0 = (s, k) => Array.isArray(s.monthly) ? 0 : (s.monthly?.[k] || 0);

  const colTops = React.useMemo(() => {
    if (hlMode !== 'col') return [];
    return months.map((_, i) => {
      const vals = segments.filter(s => s.key !== 'Outlier').map(s => {
        const v = monthsOf(s)[i] || 0;
        const denom = yearTotal(s);
        const pct = denom > 0 ? v / denom : 0;
        return { key: s.key, v: pct };
      });
      vals.sort((a,b) => b.v - a.v);
      return vals.slice(0, 2).map(x => x.key);
    });
  }, [segments, hlMode]);

  const fmtCell = (v, denom) => {
    if (unit === 'num') return fmt.k(v);
    return denom > 0 ? fmt.pct(v / denom, 1) : '—';
  };

  return (
    <div className="card seg-col-card">
      <div className="card-head">
        <div>
          <div className="card-title">Monthly visit trend</div>
          <div className="card-sub">
            {timeView === 'series' ? 'Per-segment visits May→Apr.' : 'Per-segment visits Jan→Dec.'}
          </div>
        </div>
        <div className="card-controls">
          <div className="metric-toggle unit-toggle">
            <button className={timeView === 'series' ? 'active' : ''} onClick={() => setTimeView('series')}>Series</button>
            <button className={timeView === 'pattern' ? 'active' : ''} onClick={() => setTimeView('pattern')}>Pattern</button>
          </div>
          {view === 'table' && (
            <div className="metric-toggle unit-toggle">
              <button className={unit === 'num' ? 'active' : ''} onClick={() => setUnit('num')}>#</button>
              <button className={unit === 'pct' ? 'active' : ''} onClick={() => setUnit('pct')}>%</button>
            </div>
          )}
          {view === 'table' && (
            <div className="metric-toggle unit-toggle" title="Highlight Top 2">
              <button className={hlMode === 'row' ? 'active' : ''} onClick={() => setHlMode('row')}>Row Top 2</button>
              <button className={hlMode === 'col' ? 'active' : ''} onClick={() => setHlMode('col')}>Col Top 2</button>
            </div>
          )}
          <ViewToggle view={view} setView={setView} />
        </div>
      </div>
      {view === 'chart' ? (
        <div className="trend-grid">
          {segments.map(s => {
            const m = monthsOf(s);
            const max = Math.max(...m, 1);
            const points = m.map((v, i) => {
              const x = (i / Math.max(m.length - 1, 1)) * 100;
              const y = 100 - (v / max) * 100;
              return `${x},${y}`;
            }).join(' ');
            const total = m.reduce((a,b)=>a+b,0);
            return (
              <div key={s.key} className="trend-cell">
                <div className="trend-head">
                  <div className="trend-name">
                    <div className="seg-chart-swatch" style={{ background: SEG_COLORS[s.key] }} />
                    <span>{s.key}</span>
                  </div>
                  <div className="trend-total">{fmt.num(total)}</div>
                </div>
                <svg viewBox="0 0 100 100" preserveAspectRatio="none" className="trend-svg">
                  <polyline points={points} fill="none" stroke={SEG_COLORS[s.key]} strokeWidth="2" vectorEffect="non-scaling-stroke" />
                  <polyline points={`0,100 ${points} 100,100`} fill={SEG_COLORS[s.key]} fillOpacity="0.12" stroke="none" />
                </svg>
                <div className="trend-axis">
                  <span>{months[0]}</span><span>{months[11]}</span>
                </div>
              </div>
            );
          })}
        </div>
      ) : (
        <div className="seg-chart-table-wrap">
          <table className="seg-chart-table monthly-trend-table">
            <thead>
              <tr>
                <th>Segment</th>
                {months.map(m => <th key={m} style={{ textAlign:'right' }}>{m}</th>)}
                <th style={{ textAlign:'right', borderLeft:'1px solid #e5e9f2' }}>Total</th>
              </tr>
            </thead>
            <tbody>
              {segments.map(s => {
                const m = monthsOf(s);
                const total = m.reduce((a,b)=>a+b,0);
                const denom = total;

                // Highlight top 2 row
                let topRowIndices = [];
                if (hlMode === 'row' && s.key !== 'Outlier') {
                  const vals = m.map((v, i) => ({ v, i }));
                  vals.sort((a,b) => b.v - a.v);
                  topRowIndices = vals.slice(0, 2).map(x => x.i);
                }

                return (
                  <tr key={s.key}>
                    <td style={{ backgroundColor: SEG_PASTEL_COLORS[s.key] }}>
                      <div className="seg-chart-table-name">
                        <div className="seg-chart-swatch" style={{ background: SEG_COLORS[s.key] }} />
                        {s.key}
                      </div>
                    </td>
                    {m.map((v,i) => {
                      let isTop = false;
                      if (hlMode === 'row') isTop = topRowIndices.includes(i);
                      else if (hlMode === 'col') isTop = colTops[i] && colTops[i].includes(s.key);
                      
                      const style = isTop ? { fontWeight: '600', color: '#1e40af', background: '#eff6ff' } : {};
                      return <td key={i} className="num" style={style}>{fmtCell(v, denom)}</td>;
                    })}
                    <td className="num" style={{ borderLeft:'1px solid #e5e9f2' }}><strong>{fmt.k(total)}</strong></td>
                  </tr>
                );
              })}
              {(() => {
                const colTotals = months.map((_, i) => segments.reduce((acc, s) => acc + (monthsOf(s)[i]||0), 0));
                const grand = segments.reduce((a,s)=>a+yearTotal(s),0);
                return (
                  <tr className="grand-total-row">
                    <td><strong>Grand Total</strong></td>
                    {colTotals.map((v,i) => <td key={i} className="num"><strong>{fmtCell(v, grand)}</strong></td>)}
                    <td className="num" style={{ borderLeft:'1px solid #e5e9f2' }}><strong>{fmt.k(grand)}</strong></td>
                  </tr>
                );
              })()}
            </tbody>
          </table>
        </div>
      )}
    </div>
  );
}

// ============================================================================
// SECTION 3: SPEND & TICKETS
// ============================================================================
function SpendSection({ data, onSelect }) {
  const segs = data.segments;
  return (
    <div className="section-grid">
      <SegmentChart
        title="Tickets won vs redeemed"
        subtitle="Toggle between metrics. 'Won' is tickets earned from gameplay; 'Redeemed' is tickets spent at the prize shop."
        segments={segs}
        metrics={[
          { key: 'pctUsers', label: 'Guest %',           value: s => s.pctUsers, format: 'pct', grandTotal: fmt.num(data.totalUsers) },
          { key: 'revPct',   label: 'Revenue %',        value: s => s.revPct,   format: 'pct', grandTotal: fmt.idr(data.totalRevenue) },
          { key: 'tixWon',   label: 'Tickets won',      value: s => s.tixWon,   format: 'num' },
          { key: 'tixRed',   label: 'Tickets redeemed', value: s => s.tixRed,   format: 'num' },
          { key: 'tixPct',   label: 'Redeem / Won %',   value: s => s.tixWon > 0 ? s.tixRed / s.tixWon : 0, format: 'pct', grandTotal: fmt.pct(segs.reduce((a,b)=>a+b.tixRed,0) / segs.reduce((a,b)=>a+b.tixWon,0)) },
        ]}
        onSelect={onSelect}
        totalFn={(ss) => `Won: ${fmt.num(ss.reduce((a,b)=>a+b.tixWon,0))} · Redeemed: ${fmt.num(ss.reduce((a,b)=>a+b.tixRed,0))}`}
        showGrandTotal={true}
      />



      <SegmentChart
        title="Load amount distribution (IDR)"
        subtitle="Share of total load amount per band — what size of top-up does each cohort prefer?"
        segments={segs}
        mode="stacked"
        valuesAreRatios={true}
        leadingMetrics={[
          { key: 'pctUsers', label: 'Guest %',   value: s => s.pctUsers, format: 'pct', grandTotal: fmt.num(data.totalUsers) },
          { key: 'revPct',   label: 'Revenue %', value: s => s.revPct,   format: 'pct', grandTotal: fmt.idr(data.totalRevenue) },
        ]}
        stackKeys={SEGMENT_DATA.LOAD_AMOUNT_BANDS.map((b, i) => ({
          key: b, label: b,
          color: ['#cdd3e3','#8aa0d6','#5a76c7','#2e4a9f','#1a2a5e','#b58e00','#e63329'][i],
          value: s => (s.loadDist[i] || 0),
        }))}
        onSelect={onSelect}
        showTotal={false}
        showTotalColumn={false}
        showGrandTotal={true}
        highlightTopN={2}
        highlightModeDefault="col"
        showHighlightToggle={true}
      />
    </div>
  );
}

// ============================================================================
// SECTION 4: GAMES & REDEMPTION
// ============================================================================
function GamesSection({ data, onSelect, venue }) {
  const segs = data.segments;
  return (
    <div className="section-grid">
      <GameCategoryMix segments={segs} onSelect={onSelect} venue={venue} grandTotal={data.grandTotal} />

      <TopGamesCard segments={segs} onSelect={onSelect} />

      <SegmentChart
        title="Redemption category mix"
        subtitle="Share of redeemed value across prize categories — what kinds of prizes does each cohort take home?"
        segments={segs}
        mode="stacked"
        valuesAreRatios={true}
        stackKeys={SEGMENT_DATA.REDEEM_CATS.map((c, i) => ({
          key: c, label: c,
          color: ['#1a2a5e','#e63329','#5a76c7','#f5d616','#2e4a9f','#b58e00','#8aa0d6','#cdd3e3','#9aa3bf'][i],
          value: s => (s.redeemDist[i] || 0),
        }))}
        onSelect={onSelect}
        showTotal={false}
        showTotalColumn={false}
        showGrandTotal={true}
        highlightTopN={2}
        highlightModeDefault="col"
        showHighlightToggle={true}
      />

      <TopTrophiesCard segments={segs} onSelect={onSelect} />
    </div>
  );
}

function TopTrophiesCard({ segments, onSelect }) {
  const [activeSeg, setActiveSeg] = React.useState(segments[0].key);
  const [view, setView] = React.useState('table');
  const seg = segments.find(s => s.key === activeSeg) || segments[0];
  return (
    <div className="card seg-col-card">
      <div className="card-head">
        <div>
          <div className="card-title">Trophy Redeem</div>
          <div className="card-sub">Highest-value prizes redeemed by each cohort. Switch segment to compare.</div>
        </div>
        <div className="card-controls">
          <ViewToggle view={view} setView={setView} />
        </div>
      </div>
      <div className="seg-tab-strip">
        {segments.map(s => (
          <button key={s.key}
                  className={`seg-tab-pill ${activeSeg === s.key ? 'active' : ''}`}
                  onClick={() => setActiveSeg(s.key)}>
            <span className="seg-chart-swatch" style={{ background: SEG_COLORS[s.key] }}/>
            {s.key}
          </button>
        ))}
      </div>
      {view === 'chart' ? (
        <div className="trophy-grid">
          {seg.topTrophies.length ? seg.topTrophies.map(t => (
            <div key={t.rank} className="trophy-card">
              <div className="trophy-rank">#{t.rank}</div>
              <div className="trophy-name">{t.name}</div>
              <div className="trophy-meta">
                <span><strong>{fmt.num(t.cost)}</strong> tix</span>
                <span>×{t.qty} taken</span>
                <span>{t.users} guest{t.users !== 1 ? 's' : ''}</span>
              </div>
            </div>
          )) : <div className="empty-state">No trophy data for this segment.</div>}
        </div>
      ) : (
        <div className="seg-chart-table-wrap">
          <table className="seg-chart-table">
            <thead>
              <tr>
                <th>#</th><th>Item</th>
                <th style={{ textAlign: 'right' }}>Tickets</th>
                <th style={{ textAlign: 'right' }}>Qty taken</th>
                <th style={{ textAlign: 'right' }}>Unique guests</th>
              </tr>
            </thead>
            <tbody>
              {seg.topTrophies.map(t => (
                <tr key={t.rank}>
                  <td>#{t.rank}</td>
                  <td>{t.name}</td>
                  <td className="num">{fmt.num(t.cost)}</td>
                  <td className="num">{t.qty}</td>
                  <td className="num">{t.users}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      )}
    </div>
  );
}

function TopGamesCard({ segments, onSelect }) {
  const [activeSeg, setActiveSeg] = React.useState(segments[0].key);
  const [view, setView] = React.useState('table');
  const seg = segments.find(s => s.key === activeSeg) || segments[0];
  const games = seg.topGames || [];

  // Category color mapping for visual consistency
  const catColor = {
    "Ticket Game":         '#1a2a5e',
    "Prize Game":          '#e63329',
    "Standard Video Game": '#5a76c7',
    "Attractions":         '#f5d616',
    "Non Game":            '#b58e00',
    "Std Non Video Game":  '#8aa0d6',
    "Ticket Eater":        '#9aa3bf',
  };

  return (
    <div className="card seg-col-card">
      <div className="card-head">
        <div>
          <div className="card-title">Top 5 game plays per segment</div>
          <div className="card-sub">Most-played games by each cohort. Bars show play volume; colors mark game category.</div>
        </div>
        <div className="card-controls">
          <ViewToggle view={view} setView={setView} />
        </div>
      </div>
      <div className="seg-tab-strip">
        {segments.map(s => (
          <button key={s.key}
                  className={`seg-tab-pill ${activeSeg === s.key ? 'active' : ''}`}
                  onClick={() => setActiveSeg(s.key)}>
            <span className="seg-chart-swatch" style={{ background: SEG_COLORS[s.key] }}/>
            {s.key}
          </button>
        ))}
      </div>
      {view === 'chart' ? (() => {
        const max = Math.max(...games.map(g => g.plays), 1);
        return (
          <div className="game-bar-list">
            {games.length ? games.map(g => (
              <div key={g.rank} className="game-bar-row">
                <div className="game-bar-rank">#{g.rank}</div>
                <div className="game-bar-name">
                  <div className="game-bar-title">{g.name}</div>
                  <div className="game-bar-cls">
                    <span className="game-bar-pill" style={{ background: catColor[g.cat] || '#5a76c7' }}>{g.cat}</span>
                    <span className="game-bar-cls-text">{g.cls}</span>
                  </div>
                </div>
                <div className="game-bar-track-wrap">
                  <div className="game-bar-track">
                    <div className="game-bar-fill"
                         style={{ width: `${(g.plays/max)*100}%`, background: catColor[g.cat] || '#5a76c7' }} />
                  </div>
                  <div className="game-bar-stats">
                    <span><strong>{fmt.num(g.plays)}</strong> plays</span>
                    <span>{fmt.num(g.players)} players</span>
                  </div>
                </div>
              </div>
            )) : <div className="empty-state">No game data for this segment.</div>}
          </div>
        );
      })() : (
        <div className="seg-chart-table-wrap">
          <table className="seg-chart-table">
            <thead>
              <tr>
                <th>#</th><th>Game</th><th>Class</th><th>Category</th>
                <th style={{ textAlign:'right' }}>Plays</th>
                <th style={{ textAlign:'right' }}>Players</th>
                <th style={{ textAlign:'right' }}>Plays / player</th>
              </tr>
            </thead>
            <tbody>
              {games.map(g => (
                <tr key={g.rank}>
                  <td>#{g.rank}</td>
                  <td>{g.name}</td>
                  <td>{g.cls}</td>
                  <td>
                    <span className="game-bar-pill" style={{ background: catColor[g.cat] || '#5a76c7' }}>{g.cat}</span>
                  </td>
                  <td className="num">{fmt.num(g.plays)}</td>
                  <td className="num">{fmt.num(g.players)}</td>
                  <td className="num">{(g.plays/Math.max(g.players,1)).toFixed(1)}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      )}
    </div>
  );
}

// ============================================================================
// MAIN OVERVIEW
// ============================================================================
function OverviewView({ data, venue, section, onSelectSegment }) {
  const activeSection = section || 'composition';

  return (
    <div>
      <div className="page-head">
        <div>
          <h1>Guest Segmentation Overview</h1>
        </div>
      </div>

      {activeSection === 'composition' && <CompositionSection data={data} onSelect={onSelectSegment} />}
      {activeSection === 'engagement'  && <EngagementSection  data={data} onSelect={onSelectSegment} />}
      {activeSection === 'spend'       && <SpendSection       data={data} onSelect={onSelectSegment} />}
      {activeSection === 'games'       && <GamesSection       data={data} onSelect={onSelectSegment} venue={venue} />}
    </div>
  );
}

// Game category mix — uses gameByCat directly from TSV data
function GameCategoryMix({ segments, onSelect, venue, grandTotal }) {
  const [view, setView] = React.useState('table');
  const [unit, setUnit] = React.useState('pct'); // 'pct' | 'num'
  const cats = [
    { key:'stdVideo',    label:'Standard Video Game',    color:'#5a76c7' },
    { key:'prize',       label:'Prize Game',             color:'#e63329' },
    { key:'attractions', label:'Attractions',            color:'#f5d616' },
    { key:'ticketGame',  label:'Ticket Game',            color:'#1a2a5e' },
    { key:'stdNonVideo', label:'Standard Game (Non Video)', color:'#8aa0d6' },
  ];

  const denomFor = (s) => cats.reduce((acc, c) => acc + (s.gameByCat[c.key] || 0), 0);
  const valFor = (s, catKey) => s.gameByCat[catKey] || 0;

  const colTops = React.useMemo(() => {
    return cats.map(c => {
      const vals = segments.filter(s => s.key !== 'Outlier').map(s => {
        const denom = denomFor(s);
        const v = valFor(s, c.key);
        const pct = denom > 0 ? v / denom : 0;
        return { key: s.key, v: pct };
      });
      vals.sort((a,b) => b.v - a.v);
      return vals.slice(0, 2).map(x => x.key);
    });
  }, [segments]);

  return (
    <div className="card seg-col-card">
      <div className="card-head">
        <div>
          <div className="card-title">Gameplay</div>
          <div className="card-sub">Key gameplay metrics and share of plays per game category.</div>
        </div>
        <div className="card-controls">
          {view === 'table' && (
            <div className="metric-toggle unit-toggle">
              <button className={unit === 'pct' ? 'active' : ''} onClick={() => setUnit('pct')}>%</button>
              <button className={unit === 'num' ? 'active' : ''} onClick={() => setUnit('num')}>#</button>
            </div>
          )}
          <div className="view-toggle" title={view === 'chart' ? 'Switch to table' : 'Switch to chart'}>
            <button className={view === 'chart' ? 'active' : ''} onClick={() => setView('chart')} aria-label="Chart view">
              <svg width="14" height="14" viewBox="0 0 14 14" fill="none">
                <rect x="1" y="8" width="2.5" height="5" fill="currentColor"/>
                <rect x="5.75" y="4" width="2.5" height="9" fill="currentColor"/>
                <rect x="10.5" y="6" width="2.5" height="7" fill="currentColor"/>
              </svg>
            </button>
            <button className={view === 'table' ? 'active' : ''} onClick={() => setView('table')} aria-label="Table view">
              <svg width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="currentColor" strokeWidth="1.4">
                <rect x="1" y="2" width="12" height="10" rx="1"/>
                <line x1="1" y1="6" x2="13" y2="6"/>
                <line x1="5" y1="2" x2="5" y2="12"/>
              </svg>
            </button>
          </div>
        </div>
      </div>
      {view === 'chart' ? (
        <div className="seg-stack-list">
          {segments.map(s => {
            const denom = denomFor(s);
            return (
              <div key={s.key} className="seg-stack-row">
                <div className="seg-stack-label">
                  <div className="seg-chart-swatch" style={{ background: SEG_COLORS[s.key] }}/>
                  <span>{s.key}</span>
                </div>
                <div className="seg-stack-bar">
                  {denom > 0 ? cats.map(c => {
                    const v = valFor(s, c.key);
                    const pct = (v / denom) * 100;
                    if (pct < 0.5) return null;
                    return (
                      <div key={c.key} className="seg-stack-seg"
                           style={{ width: pct+'%', background: c.color }}
                           title={`${c.label}: ${pct.toFixed(1)}% (${fmt.num(v)})`}>
                        {pct > 7 && <span className="seg-stack-num">{Math.round(pct)}%</span>}
                      </div>
                    );
                  }) : <div className="seg-stack-empty">No data</div>}
                </div>
                <div className="seg-stack-total">{fmt.num(denom)}</div>
              </div>
            );
          })}
          <div className="seg-stack-legend">
            {cats.map(c => (
              <div className="seg-stack-legend-item" key={c.key}>
                <div className="seg-chart-swatch" style={{ background: c.color }}/>
                <span>{c.label}</span>
              </div>
            ))}
          </div>
        </div>
      ) : (
        <div className="seg-chart-table-wrap">
          <table className="seg-chart-table">
            <thead>
              <tr>
                <th>Segment</th>
                <th style={{ textAlign:'right' }}>Guest %</th>
                <th style={{ textAlign:'right' }}>Revenue %</th>
                <th style={{ textAlign:'right' }}>Total plays</th>
                <th style={{ textAlign:'right' }}>Avg per guest</th>
                {cats.map(c => <th key={c.key} style={{ textAlign:'right' }}>{c.label}</th>)}
              </tr>
            </thead>
            <tbody>
              {segments.map(s => {
                const denom = denomFor(s);
                return (
                  <tr key={s.key}>
                    <td style={{ backgroundColor: SEG_PASTEL_COLORS[s.key] }}>
                      <div className="seg-chart-table-name">
                        <div className="seg-chart-swatch" style={{ background: SEG_COLORS[s.key] }} />
                        {s.key}
                      </div>
                    </td>
                    <td className="num">{fmt.pct(s.pctUsers)}</td>
                    <td className="num">{fmt.pct(s.revPct)}</td>
                    <td className="num">{fmt.num(s.gameTotal)}</td>
                    <td className="num">{fmt.num(s.gameAvg)}</td>
                    {cats.map((c, i) => {
                      const v = valFor(s, c.key);
                      const isTop = colTops[i] && colTops[i].includes(s.key);
                      const style = isTop ? { fontWeight: '600', color: '#1e40af', background: '#eff6ff' } : {};
                      return <td key={c.key} className="num" style={style}>{denom > 0 ? (unit === 'num' ? fmt.num(v) : fmt.pct(v/denom, 1)) : '—'}</td>;
                    })}
                  </tr>
                );
              })}
              {(() => {
                const totals = cats.map(c => segments.reduce((acc, s) => acc + valFor(s, c.key), 0));
                const grand = segments.reduce((acc, s) => acc + denomFor(s), 0);
                const gtGameAvg = grandTotal ? grandTotal.gameAvg : null;
                return (
                  <tr className="grand-total-row">
                    <td><strong>GRAND TOTAL</strong></td>
                    <td className="num"><strong>{fmt.num(segments.reduce((a,b)=>a+b.userCount,0))}</strong></td>
                    <td className="num"><strong>{fmt.idr(segments.reduce((a,b)=>a+b.revenue,0))}</strong></td>
                    <td className="num"><strong>{fmt.num(segments.reduce((a,b)=>a+b.gameTotal,0))}</strong></td>
                    <td className="num"><strong>{gtGameAvg != null ? fmt.num(gtGameAvg) : '—'}</strong></td>
                    {cats.map((c, i) => (
                      <td key={c.key} className="num"><strong>{grand > 0 ? (unit === 'num' ? fmt.num(totals[i]) : fmt.pct(totals[i]/grand, 1)) : '—'}</strong></td>
                    ))}
                  </tr>
                );
              })()}
            </tbody>
          </table>
        </div>
      )}
    </div>
  );
}

window.OverviewView = OverviewView;