// Marketing OS — Dashboard v2

function Stat({ label, value, sub, hint, highlight, formula }) {
  return (
    <div className={`stat ${highlight ? 'highlight' : ''}`}>
      {highlight && <div className="stat-accent"/>}
      <div className="stat-label" title={formula || ''}>{label}</div>
      <div className="stat-value">{value}{sub && <span className="stat-value-sub">{sub}</span>}</div>
      {hint && <div className="stat-delta flat" style={{fontSize:11}}>{hint}</div>}
    </div>
  );
}

function FilterBar({ filter, setFilter, currentUser, visibleUsers, onClear }) {
  const canSeeTeams = currentUser.role !== 'staff';
  const canSeeUsers = currentUser.role !== 'staff';
  const teamOptions = window.TEAMS;
  const subteamOptions = window.SUBTEAMS.filter(s => {
    if (window.hasPerm(currentUser.role, 'view_all_data')) return true;
    if (currentUser.role === 'team_lead') return s.teamId === currentUser.teamId;
    if (currentUser.role === 'sub_lead')  return s.id === currentUser.subteamId;
    return false;
  });
  const updateF = (k, v) => setFilter(f => ({ ...f, [k]: v }));
  const isCustom = filter.range === 'custom';

  return (
    <div className="filter-bar" style={{flexWrap:'wrap'}}>
      <div className="search-box">
        <span className="icon"><Icon name="search" size={14}/></span>
        <input className="input" placeholder="ค้นหาเซียน, รหัส, หมายเหตุ..." value={filter.q} onChange={e => updateF('q', e.target.value)}/>
      </div>

      <select className="select" value={filter.range} onChange={e => updateF('range', e.target.value)}>
        <optgroup label="รายวัน">
          <option value="today">วันนี้</option>
          <option value="yesterday">เมื่อวาน</option>
          <option value="7">7 วันล่าสุด</option>
          <option value="14">14 วันล่าสุด</option>
          <option value="30">30 วันล่าสุด</option>
        </optgroup>
        <optgroup label="รายเดือน">
          <option value="this_month">เดือนนี้</option>
          <option value="last_month">เดือนก่อน</option>
          <option value="90">3 เดือนล่าสุด</option>
          <option value="180">6 เดือนล่าสุด</option>
          <option value="365">12 เดือนล่าสุด</option>
        </optgroup>
        <option value="custom">ระบุวันที่เอง…</option>
        <option value="all">ทั้งหมด</option>
      </select>

      {isCustom && (
        <div className="row" style={{gap: 6, background: 'var(--gold-tint)', padding:'4px 10px', borderRadius: 8, border:'1px solid var(--gold-soft)'}}>
          <Icon name="calendar" size={12} style={{color:'var(--gold)'}}/>
          <input type="date" className="input" style={{padding:'5px 8px', fontSize:12, minWidth:130, width:130}}
                 value={filter.from || ''} onChange={e => updateF('from', e.target.value)} max="2026-05-20"/>
          <span style={{fontSize:11, color:'var(--ink-3)'}}>ถึง</span>
          <input type="date" className="input" style={{padding:'5px 8px', fontSize:12, minWidth:130, width:130}}
                 value={filter.to || ''} onChange={e => updateF('to', e.target.value)} max="2026-05-20"/>
        </div>
      )}

      {canSeeTeams && (
        <select className="select" value={filter.team} onChange={e => updateF('team', e.target.value)}>
          <option value="">ทุกทีม</option>
          {teamOptions.map(t => <option key={t.id} value={t.id}>{t.name}</option>)}
        </select>
      )}

      {canSeeTeams && (
        <select className="select" value={filter.subteam} onChange={e => updateF('subteam', e.target.value)}>
          <option value="">ทุกทีมย่อย</option>
          {subteamOptions
            .filter(s => !filter.team || s.teamId === filter.team)
            .map(s => <option key={s.id} value={s.id}>{s.name}</option>)}
        </select>
      )}

      {canSeeUsers && (
        <select className="select" value={filter.user} onChange={e => updateF('user', e.target.value)}>
          <option value="">ทุกเซียน</option>
          {visibleUsers
            .filter(u => u.role === 'staff' || u.role === 'sub_lead')
            .filter(u => !filter.team || u.teamId === filter.team)
            .filter(u => !filter.subteam || u.subteamId === filter.subteam)
            .map(u => <option key={u.id} value={u.id}>{u.code} · {u.name.replace(/^คุณ/,'')}</option>)}
        </select>
      )}

      <select className="select" value={filter.method} onChange={e => updateF('method', e.target.value)}>
        <option value="">ทุกวิธี</option>
        {window.METHODS.map(m => <option key={m.id} value={m.id}>{m.label}</option>)}
      </select>

      <select className="select" value={filter.website} onChange={e => updateF('website', e.target.value)}>
        <option value="">ทุกเว็บไซต์</option>
        {window.WEBSITES.map(w => <option key={w.id} value={w.id}>{w.label}</option>)}
      </select>

      <div style={{flex: 1}}/>

      <button className="btn btn-ghost btn-sm" onClick={onClear}>
        <Icon name="refresh" size={12}/> ล้าง
      </button>
      <button className="btn btn-secondary btn-sm">
        <Icon name="download" size={12}/> Export CSV
      </button>
    </div>
  );
}

function dateRangeFor(rangeKey, customFrom, customTo) {
  // Returns [fromDateStr, toDateStr] inclusive (YYYY-MM-DD), or null for "all"
  if (!rangeKey || rangeKey === 'all') return null;
  const today = new Date('2026-05-20');
  const iso = (d) => d.toISOString().slice(0,10);
  if (rangeKey === 'custom') {
    if (!customFrom && !customTo) return null;
    return [customFrom || '0000-00-00', customTo || '9999-12-31'];
  }
  if (rangeKey === 'today')     return [iso(today), iso(today)];
  if (rangeKey === 'yesterday') {
    const y = new Date(today); y.setDate(y.getDate() - 1);
    return [iso(y), iso(y)];
  }
  if (rangeKey === 'this_month') {
    const from = new Date(today.getFullYear(), today.getMonth(), 1);
    return [iso(from), iso(today)];
  }
  if (rangeKey === 'last_month') {
    const from = new Date(today.getFullYear(), today.getMonth() - 1, 1);
    const to   = new Date(today.getFullYear(), today.getMonth(),  0);
    return [iso(from), iso(to)];
  }
  const days = +rangeKey;
  if (!isNaN(days) && days > 0) {
    const from = new Date(today); from.setDate(from.getDate() - days);
    return [iso(from), iso(today)];
  }
  return null;
}

function applyFilter(entries, filter) {
  let list = entries;
  const r = dateRangeFor(filter.range, filter.from, filter.to);
  if (r) list = list.filter(e => e.date >= r[0] && e.date <= r[1]);
  if (filter.team)    list = list.filter(e => e.teamId === filter.team);
  if (filter.subteam) list = list.filter(e => e.subteamId === filter.subteam);
  if (filter.user)    list = list.filter(e => e.userId === filter.user);
  if (filter.method)  list = list.filter(e => e.methods?.includes(filter.method));
  if (filter.website) list = list.filter(e => e.website === filter.website);
  if (filter.q) {
    const q = filter.q.toLowerCase();
    list = list.filter(e =>
      (e.userName || '').toLowerCase().includes(q) ||
      (e.userNick || '').toLowerCase().includes(q) ||
      (e.userId || '').toLowerCase().includes(q) ||
      (e.note || '').toLowerCase().includes(q)
    );
  }
  return list;
}

function applyExpenseFilter(expenses, filter) {
  let list = expenses;
  const r = dateRangeFor(filter.range, filter.from, filter.to);
  if (r) list = list.filter(e => e.date >= r[0] && e.date <= r[1]);
  if (filter.team)    list = list.filter(e => e.teamId === filter.team);
  if (filter.subteam) list = list.filter(e => e.subteamId === filter.subteam);
  if (filter.user)    list = list.filter(e => e.userId === filter.user);
  return list;
}

function aggregate(entries, expenses) {
  const sum = (k) => entries.reduce((s, e) => s + (+e[k] || 0), 0);
  const totalSignup        = sum('signup');
  const totalSignupDeposit = sum('signupDeposit');
  const totalFirstDeposit  = sum('firstDeposit');
  const totalDailyDeposit  = sum('dailyDeposit');
  const totalAdSpend       = sum('adSpendTHB');
  const totalWithdrawAds   = entries.reduce((s, e) => s + (+e.withdrawTHB || +e.withdraw || 0), 0);
  const totalExpenses      = expenses.reduce((s, e) => s + (+e.amountTHB || 0), 0);
  const convRate = totalSignup ? (totalSignupDeposit / totalSignup * 100) : 0;
  const cpaSignup = totalSignup ? (totalAdSpend / totalSignup) : 0;
  // Distinct active days in the entry set → avg ad spend / day
  const distinctDays = new Set(entries.map(e => e.date)).size || 1;
  const avgAdSpendPerDay = totalAdSpend / distinctDays;
  return {
    totalSignup, totalSignupDeposit, totalFirstDeposit, totalDailyDeposit,
    totalAdSpend, totalWithdrawAds, totalExpenses, convRate, cpaSignup,
    avgAdSpendPerDay, distinctDays,
    count: entries.length,
  };
}

// ---------- Trend chart: dual-line over dates (signup vs daily deposit) ----------
function TrendChart({ entries }) {
  // Aggregate per date
  const map = new Map();
  for (const e of entries) {
    const cur = map.get(e.date) || { date: e.date, signup: 0, deposit: 0 };
    cur.signup  += +e.signup || 0;
    cur.deposit += +e.dailyDeposit || 0;
    map.set(e.date, cur);
  }
  const data = [...map.values()].sort((a,b) => a.date.localeCompare(b.date));

  if (data.length < 2) return <div className="muted" style={{padding:40, textAlign:'center'}}>ข้อมูลน้อยเกินไป — ต้องมีอย่างน้อย 2 วัน</div>;

  const W = 700, H = 280, PAD_L = 48, PAD_R = 48, PAD_T = 16, PAD_B = 40;
  const innerW = W - PAD_L - PAD_R;
  const innerH = H - PAD_T - PAD_B;

  const maxSignup  = Math.max(...data.map(d => d.signup),  1);
  const maxDeposit = Math.max(...data.map(d => d.deposit), 1);

  const xFor = (i) => PAD_L + (data.length === 1 ? 0 : (i / (data.length - 1)) * innerW);
  const ySignup  = (v) => PAD_T + innerH - (v / maxSignup)  * innerH;
  const yDeposit = (v) => PAD_T + innerH - (v / maxDeposit) * innerH;

  const pathSignup  = data.map((d, i) => `${i === 0 ? 'M' : 'L'} ${xFor(i)} ${ySignup(d.signup)}`).join(' ');
  const pathDeposit = data.map((d, i) => `${i === 0 ? 'M' : 'L'} ${xFor(i)} ${yDeposit(d.deposit)}`).join(' ');

  // Tick labels: show ~6 evenly spaced
  const tickIdx = (() => {
    if (data.length <= 8) return data.map((_, i) => i);
    const step = Math.ceil(data.length / 7);
    const r = [];
    for (let i = 0; i < data.length; i += step) r.push(i);
    if (r[r.length-1] !== data.length - 1) r.push(data.length - 1);
    return r;
  })();

  const yTicks = 4;

  return (
    <div>
      <div className="row" style={{gap:18, fontSize: 12, marginBottom: 8, color:'var(--ink-3)'}}>
        <span className="row" style={{gap:6}}><span style={{width:18, height:2, background:'var(--ink)'}}/> ยอดสมัคร (คน)</span>
        <span className="row" style={{gap:6}}><span style={{width:18, height:2, background:'var(--gold)'}}/> ยอดฝากทั้งวัน (THB)</span>
        <span style={{marginLeft:'auto', fontSize:11}}>{data.length} วัน</span>
      </div>
      <svg viewBox={`0 0 ${W} ${H}`} style={{width:'100%', height: 300}}>
        {/* Horizontal grid + Y-axis ticks */}
        {Array.from({length: yTicks + 1}).map((_, i) => {
          const y = PAD_T + (innerH / yTicks) * i;
          const valS = Math.round(maxSignup  - (maxSignup  / yTicks) * i);
          const valD = (maxDeposit - (maxDeposit / yTicks) * i);
          return (
            <g key={'g-' + i}>
              <line x1={PAD_L} y1={y} x2={W - PAD_R} y2={y} stroke="var(--line)" strokeDasharray={i === yTicks ? '0' : '3 3'}/>
              <text x={PAD_L - 6} y={y + 3} textAnchor="end" fontSize="10" fill="var(--ink-3)" fontFamily="var(--mono)">{valS}</text>
              <text x={W - PAD_R + 6} y={y + 3} textAnchor="start" fontSize="10" fill="var(--gold)" fontFamily="var(--mono)">
                {valD >= 1e6 ? (valD/1e6).toFixed(1)+'M' : valD >= 1000 ? (valD/1000).toFixed(0)+'k' : Math.round(valD)}
              </text>
            </g>
          );
        })}

        {/* X-axis labels */}
        {tickIdx.map(i => {
          const d = new Date(data[i].date);
          const label = `${d.getDate()}/${d.getMonth()+1}`;
          return <text key={'x-' + i} x={xFor(i)} y={H - PAD_B + 14} textAnchor="middle" fontSize="10" fill="var(--ink-3)" fontFamily="var(--mono)">{label}</text>;
        })}

        {/* Axis labels */}
        <text x={PAD_L - 36} y={PAD_T - 4} fontSize="10" fill="var(--ink-3)">สมัคร</text>
        <text x={W - PAD_R + 4} y={PAD_T - 4} fontSize="10" fill="var(--gold)">฿ ฝาก</text>

        {/* Lines */}
        <path d={pathDeposit} fill="none" stroke="var(--gold)" strokeWidth="2"/>
        <path d={pathSignup}  fill="none" stroke="var(--ink)"  strokeWidth="2"/>

        {/* Points */}
        {data.map((d, i) => (
          <g key={'pt-' + i}>
            <circle cx={xFor(i)} cy={yDeposit(d.deposit)} r="3" fill="var(--gold)">
              <title>{`${d.date}\nยอดฝาก ${window.fmtTHB(d.deposit)}`}</title>
            </circle>
            <circle cx={xFor(i)} cy={ySignup(d.signup)} r="3" fill="var(--ink)">
              <title>{`${d.date}\nยอดสมัคร ${d.signup} คน`}</title>
            </circle>
          </g>
        ))}
      </svg>
    </div>
  );
}

// ---------- Top Sales table ----------
function TopSales({ entries }) {
  const map = new Map();
  for (const e of entries) {
    const cur = map.get(e.userId) || {
      userId: e.userId, name: e.userName, nick: e.userNick, teamId: e.teamId, subteamId: e.subteamId,
      signup: 0, adSpend: 0, count: 0
    };
    cur.signup  += +e.signup || 0;
    cur.adSpend += +e.adSpendTHB || 0;
    cur.count++;
    map.set(e.userId, cur);
  }
  const rows = [...map.values()]
    .map(r => ({ ...r, cpa: r.signup ? (r.adSpend / r.signup) : 0 }))
    .sort((a,b) => b.signup - a.signup);

  if (!rows.length) return <div className="muted" style={{padding:24, textAlign:'center'}}>ไม่มีข้อมูล</div>;

  return (
    <div style={{maxHeight: 460, overflowY: 'auto'}}>
      <table className="table" style={{tableLayout:'auto'}}>
        <thead>
          <tr>
            <th style={{width:48}}>อันดับ</th>
            <th>ชื่อ</th>
            <th>ทีม</th>
            <th className="right">ยอดสมัคร</th>
            <th className="right">ค่าแอด</th>
            <th className="right">ต้นทุน/หัว</th>
          </tr>
        </thead>
        <tbody>
          {rows.map((r, i) => {
            const team = window.getTeam(r.teamId);
            const sub  = window.getSubteam(r.subteamId);
            return (
              <tr key={r.userId}>
                <td>
                  <span style={{
                    display:'inline-grid', placeItems:'center',
                    width:24, height:24, borderRadius:6,
                    background: i < 3 ? 'var(--ink)' : 'var(--bg-sunken)',
                    color: i < 3 ? 'var(--gold)' : 'var(--ink-3)',
                    fontSize: 11, fontWeight: 600,
                  }}>{i+1}</span>
                </td>
                <td>
                  <div className="row" style={{gap: 8, minWidth: 0}}>
                    <div className="avatar" style={{width:24, height:24, fontSize:9, flexShrink: 0}}>{window.initials(r.name)}</div>
                    <div style={{minWidth: 0, overflow:'hidden'}}>
                      <div style={{fontWeight: 500, color:'var(--ink)', whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis'}}>{r.name.replace(/^คุณ/,'')}</div>
                      {r.nick && <div style={{fontSize:11, color:'var(--ink-3)'}}>{r.nick}</div>}
                    </div>
                  </div>
                </td>
                <td>
                  <div style={{fontSize: 12.5, color:'var(--ink-2)'}}>{team?.name || '-'}</div>
                  {sub && <div style={{fontSize: 11, color:'var(--ink-3)'}}>{sub.name}</div>}
                </td>
                <td className="num right" style={{fontWeight: 500, color:'var(--ink)'}}>{window.fmtNum(r.signup)} <span style={{color:'var(--ink-3)', fontWeight:400}}>คน</span></td>
                <td className="num right">{window.fmtTHB(r.adSpend)}</td>
                <td className="num right">{window.fmtTHB(r.cpa)}</td>
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );
}

// ---------- Expense aggregation by item ----------
function ExpenseRanking({ expenses }) {
  const map = new Map();
  for (const x of expenses) {
    const key = x.item.trim().toLowerCase();
    const cur = map.get(key) || { item: x.item, category: x.category, count: 0, total: 0 };
    cur.count++;
    cur.total += +x.amountTHB || 0;
    map.set(key, cur);
  }
  const rows = [...map.values()].sort((a, b) => b.total - a.total);
  const grand = rows.reduce((s, r) => s + r.total, 0);

  if (!rows.length) return <div className="muted" style={{padding:24, textAlign:'center'}}>ไม่มีข้อมูลค่าใช้จ่าย</div>;

  const max = rows[0]?.total || 1;

  return (
    <div style={{maxHeight: 460, overflowY: 'auto'}}>
      <table className="table" style={{tableLayout:'fixed'}}>
        <thead>
          <tr>
            <th style={{width: 40}}>#</th>
            <th>รายการ</th>
            <th style={{width: 130}}>ประเภท</th>
            <th className="right" style={{width: 70}}>ครั้ง</th>
            <th className="right" style={{width: 130}}>รวม (THB)</th>
          </tr>
        </thead>
        <tbody>
          {rows.map((r, i) => {
            const cat = window.EXPENSE_CATEGORIES.find(c => c.id === r.category);
            const pct = (r.total / max) * 100;
            return (
              <tr key={r.item}>
                <td>
                  <span style={{
                    display:'inline-grid', placeItems:'center',
                    width:22, height:22, borderRadius:6,
                    background: i < 3 ? 'var(--ink)' : 'var(--bg-sunken)',
                    color: i < 3 ? 'var(--gold)' : 'var(--ink-3)',
                    fontSize: 11, fontWeight: 600,
                  }}>{i+1}</span>
                </td>
                <td>
                  <div style={{fontWeight:500, color:'var(--ink)', whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis'}}>{r.item}</div>
                  <div style={{position:'relative', marginTop:6, height: 4, background:'var(--bg-sunken)', borderRadius: 2}}>
                    <div style={{position:'absolute', left:0, top:0, bottom:0, width: pct + '%', background:'var(--gold)', borderRadius: 2}}/>
                  </div>
                </td>
                <td><span className="badge outline" style={{fontSize:10}}>{cat?.label || r.category}</span></td>
                <td className="num right">{r.count}</td>
                <td className="num right" style={{fontWeight: 500, color:'var(--ink)'}}>{window.fmtTHB(r.total)}</td>
              </tr>
            );
          })}
        </tbody>
        <tfoot>
          <tr>
            <td colSpan="4" style={{background:'var(--bg-sunken)', fontWeight:500, color:'var(--ink)'}}>รวมทั้งหมด</td>
            <td className="num right" style={{background:'var(--bg-sunken)', fontWeight:600, color:'var(--ink)'}}>{window.fmtTHB(grand)}</td>
          </tr>
        </tfoot>
      </table>
    </div>
  );
}

function Dashboard({ currentUser, entries, expenses, visibleUsers }) {
  const [filter, setFilter] = React.useState({
    q: '', range: '30', from: '', to: '', team: '', subteam: '', user: '', method: '', website: ''
  });
  const clear = () => setFilter({ q: '', range: '30', from: '', to: '', team: '', subteam: '', user: '', method: '', website: '' });

  const filtered      = useMemo(() => applyFilter(entries, filter), [entries, filter]);
  const filteredExp   = useMemo(() => applyExpenseFilter(expenses, filter), [expenses, filter]);
  const agg           = useMemo(() => aggregate(filtered, filteredExp), [filtered, filteredExp]);

  const scopeLabel = useMemo(() => {
    if (window.hasPerm(currentUser.role, 'view_all_data')) return 'มุมมองทั้งองค์กร';
    if (currentUser.role === 'team_lead') return 'มุมมอง ' + (window.getTeam(currentUser.teamId)?.name || '');
    if (currentUser.role === 'sub_lead')  return 'มุมมอง ' + (window.getSubteam(currentUser.subteamId)?.name || '');
    return 'มุมมองข้อมูลตนเอง';
  }, [currentUser]);

  return (
    <div>
      <div className="page-head">
        <div className="page-title-block">
          <div className="page-title">ภาพรวมการทำงาน</div>
          <div className="page-desc">
            <span className="perm-chip"><Icon name="eye" size={11}/> {scopeLabel}</span>
            <span style={{marginLeft:10}}>{agg.count} รายการ · ค่าใช้จ่าย {filteredExp.length} รายการ · ข้อมูลล่าสุด {filtered[0]?.date || '-'}</span>
          </div>
        </div>
      </div>

      <FilterBar filter={filter} setFilter={setFilter} currentUser={currentUser} visibleUsers={visibleUsers} onClear={clear}/>

      {/* Pattern: ยอดสมัคร, ยอดสมัครฝาก, %สมัครฝาก, ฝากแรก, ฝากทั้งวัน */}
      <div className="stat-grid" style={{gridTemplateColumns: 'repeat(5, 1fr)'}}>
        <Stat label="ยอดสมัคร" value={window.fmtNum(agg.totalSignup)} sub="คน"/>
        <Stat label="ยอดสมัครฝาก" value={window.fmtNum(agg.totalSignupDeposit)} sub="คน"/>
        <Stat label="% สมัครฝาก" value={agg.convRate.toFixed(1)} sub="%" highlight
              formula="(Σ ยอดสมัครฝาก / Σ ยอดสมัคร) × 100"
              hint={`${window.fmtNum(agg.totalSignupDeposit)} จาก ${window.fmtNum(agg.totalSignup)} คน`}/>
        <Stat label="ฝากแรก" value={window.fmtTHB(agg.totalFirstDeposit)}/>
        <Stat label="ฝากทั้งวัน" value={window.fmtTHB(agg.totalDailyDeposit)}/>
      </div>

      {/* Pattern: ค่าแอด, ต้นทุนต่อหัว, เบิกค่าแอด, เบิกค่าใช้จ่าย */}
      <div className="stat-grid" style={{marginTop:14, gridTemplateColumns: 'repeat(4, 1fr)'}}>
        <Stat label="ค่าแอด / วัน" value={window.fmtTHB(agg.avgAdSpendPerDay)} sub="/ วัน"
              formula="ค่าแอดรวม / จำนวนวันที่มีรายการ"
              hint={`เฉลี่ยจาก ${agg.distinctDays} วัน · รวม ${window.fmtTHB(agg.totalAdSpend)}`}/>
        <Stat label="ต้นทุนต่อหัว" value={window.fmtTHB(agg.cpaSignup)} sub="/ คน"
              formula="ค่าแอดรวม / ยอดสมัคร" hint="ต้นทุนเฉลี่ยต่อยอดสมัคร 1 คน"/>
        <Stat label="เบิกค่าแอด" value={window.fmtTHB(agg.totalWithdrawAds)} hint="จากฟอร์มกรอกข้อมูล"/>
        <Stat label="เบิกค่าใช้จ่าย" value={window.fmtTHB(agg.totalExpenses)} hint="จากฟอร์มกรอกค่าใช้จ่าย"/>
      </div>

      {/* Scatter + (something) */}
      <div className="chart-grid" style={{marginTop: 18}}>
        <div className="card">
          <div className="card-header" style={{justifyContent:'space-between'}}>
            <div>
              <div className="card-title">แนวโน้ม ยอดสมัคร × ยอดฝากทั้งวัน</div>
              <div className="card-sub">เส้นแนวโน้มตามจำนวนวัน · 2 แกน Y (ซ้าย=คน, ขวา=บาท) เพื่อให้ค่าไม่โดดเกินกัน</div>
            </div>
            <button className="btn btn-ghost btn-sm"><Icon name="download" size={12}/></button>
          </div>
          <div className="card-pad">
            <TrendChart entries={filtered}/>
          </div>
        </div>

        <div className="card">
          <div className="card-header">
            <div>
              <div className="card-title">วิธีการทำงาน</div>
              <div className="card-sub">ยอดสมัครแยกตามวิธี · เรียงจากมากไปน้อย</div>
            </div>
          </div>
          <div className="card-pad">
            <MethodList entries={filtered}/>
          </div>
        </div>
      </div>

      {/* Top Sales + Expense ranking */}
      <div className="chart-grid" style={{gridTemplateColumns: '1fr 1fr'}}>
        <div className="card">
          <div className="card-header" style={{justifyContent:'space-between'}}>
            <div>
              <div className="card-title">Top Sales</div>
              <div className="card-sub">เรียงตามยอดสมัครรวม · มากสุดอยู่บน</div>
            </div>
          </div>
          <TopSales entries={filtered}/>
        </div>

        <div className="card">
          <div className="card-header" style={{justifyContent:'space-between'}}>
            <div>
              <div className="card-title">เบิกค่าใช้จ่าย (จัดอันดับ)</div>
              <div className="card-sub">รวมยอดของรายการชื่อเดียวกันอัตโนมัติ</div>
            </div>
            <button className="btn btn-ghost btn-sm"><Icon name="download" size={12}/></button>
          </div>
          <ExpenseRanking expenses={filteredExp}/>
        </div>
      </div>
    </div>
  );
}

// Method list — show signup count per method
function MethodList({ entries }) {
  const map = new Map(window.METHODS.map(m => [m.id, { id: m.id, label: m.label, icon: m.icon, count: 0, signup: 0 }]));
  for (const e of entries) {
    for (const mid of (e.methods || [])) {
      const cur = map.get(mid);
      if (cur) { cur.count++; cur.signup += +e.signup || 0; }
    }
  }
  const data = [...map.values()].sort((a,b) => b.signup - a.signup);
  if (!data.length || data.every(d => d.count === 0)) return <div className="muted" style={{padding:24, textAlign:'center'}}>ไม่มีข้อมูล</div>;
  const max = Math.max(...data.map(d => d.signup), 1);
  return (
    <div>
      {data.map(m => {
        const pct = (m.signup / max) * 100;
        return (
          <div className="row-bar" key={m.id}>
            <div className="row-bar-label row" style={{gap:8}}>
              <Icon name={m.icon} size={14} style={{color:'var(--ink-3)'}}/>
              {m.label}
            </div>
            <div className="row-bar-track"><div className="row-bar-fill dark" style={{width: pct + '%'}}/></div>
            <div className="row-bar-val">{window.fmtNum(m.signup)} <span style={{color:'var(--ink-3)', fontWeight:400}}>คน</span></div>
          </div>
        );
      })}
    </div>
  );
}

window.Dashboard = Dashboard;
window.applyFilter = applyFilter;
window.applyExpenseFilter = applyExpenseFilter;
window.dateRangeFor = dateRangeFor;
window.FilterBar = FilterBar;
