// ===== Overview + Creators views =====

function Kpi({ label, value, sub, accent }) {
  return (
    <div className={'kpi' + (accent ? ' kpi-accent' : '')}>
      <div className="kpi-label">{label}</div>
      <div className="kpi-value num">{value}</div>
      {sub && <div className="kpi-sub">{sub}</div>}
    </div>
  );
}

function BonusBreakdown({ rows }) {
  const parts = BONUS_PARTS.map((p) => ({ ...p, v: sumBy(rows, p.key) })).filter((p) => p.v > 0);
  const total = parts.reduce((s, p) => s + p.v, 0);
  if (!total) return <div className="empty">本期無獎金</div>;
  return (
    <div className="breakdown">
      <div className="stack">
        {parts.map((p) => (
          <div key={p.key} className="stack-seg" style={{ flexGrow: p.v, background: p.color }} title={`${p.label} ${fmtMoney(p.v)}`} />
        ))}
      </div>
      <div className="legend">
        {parts.map((p) => (
          <div key={p.key} className="legend-row">
            <span className="dot" style={{ background: p.color }} />
            <span className="legend-name">{p.label}<em>{p.key === 'bIncr' ? `鑽石 × ${window.RECON_RATE}%` : p.en}</em></span>
            <span className="num legend-val">{fmtMoney(p.v)}</span>
            <span className="num legend-pct">{fmtPct(p.v / total)}</span>
          </div>
        ))}
      </div>
    </div>
  );
}

function StatusPill({ value, onChange }) {
  const opt = STATUS_OPTS.find((o) => o.v === value) || STATUS_OPTS[0];
  return (
    <label className={'pill pill-' + opt.v} onClick={(e) => e.stopPropagation()}>
      <span className="pill-dot" />
      <select value={opt.v} onChange={(e) => onChange(e.target.value)}>
        {STATUS_OPTS.map((o) => <option key={o.v} value={o.v}>{o.label}</option>)}
      </select>
      <span>{opt.label}</span>
    </label>
  );
}

function SortTh({ k, sort, setSort, children, align }) {
  const on = sort.k === k;
  return (
    <th className={(align === 'r' ? 'r ' : '') + 'sortable' + (on ? ' on' : '')}
      onClick={() => setSort({ k, dir: on && sort.dir === 'desc' ? 'asc' : 'desc' })}>
      {children}<span className="caret">{on ? (sort.dir === 'desc' ? '↓' : '↑') : '↕'}</span>
    </th>
  );
}

function sortRows(rows, sort) {
  const d = sort.dir === 'desc' ? -1 : 1;
  return [...rows].sort((a, b) => {
    const x = a[sort.k], y = b[sort.k];
    if (typeof x === 'string' || typeof y === 'string') return String(x || '').localeCompare(String(y || ''), 'zh-Hant') * d;
    return ((x || 0) - (y || 0)) * d;
  });
}

// ---------- Overview ----------
function OverviewView({ rows, month, dim, setDim, status, setStatus, openStatement }) {
  const [sort, setSort] = React.useState({ k: 'bonus', dir: 'desc' });
  const totals = React.useMemo(() => ({
    diamonds: sumBy(rows, 'diamonds'), bonus: sumBy(rows, 'bonus'), payout: sumBy(rows, 'payout'), payoutTWD: sumBy(rows, 'payoutTWD'), hours: sumBy(rows, 'hours'),
    earning: rows.filter((r) => r.diamonds > 0).length, violative: rows.filter((r) => r.violative).length,
    rookie: rows.filter((r) => r.rookie).length,
  }), [rows]);
  const groups = React.useMemo(() => sortRows(aggregate(rows, dim), sort), [rows, dim, sort]);
  const maxBonus = Math.max(...groups.map((g) => g.payout), 1);
  const dimLabel = DIMENSIONS.find((d) => d.key === dim).label;
  const statusCounts = STATUS_OPTS.map((o) => ({ ...o, n: groups.filter((g) => (status[`${month}|${dim}|${g.name}`] || 'pending') === o.v).length }));

  const exportAgg = () => downloadCSV(`對帳彙總_${dimLabel}_${month}.csv`,
    [dimLabel, '主播數', '有收益主播', '鑽石', '預估獎金', '應付分潤 USD', '匯率', '匯款 TWD', '直播時數', '違規主播', '對帳狀態'],
    groups.map((g) => [g.name || '(未指定)', g.count, g.earning, g.diamonds, g.bonus.toFixed(4), g.payout.toFixed(4), window.RECON_FX, g.payoutTWD, g.hours.toFixed(2), g.violative,
      STATUS_OPTS.find((o) => o.v === (status[`${month}|${dim}|${g.name}`] || 'pending')).label]));

  return (
    <div className="view">
      <section className="kpis">
        <Kpi accent label={`應付匯款總額 (TWD · 匯率 ${window.RECON_FX})`} value={fmtTWD(totals.payoutTWD)} sub={`應付 ${fmtMoney(totals.payout)} · 預估獎金 ${fmtMoney(totals.bonus)} · 留存 ${fmtMoney(totals.bonus - totals.payout)}`} />
        <Kpi label="鑽石總數" value={fmtInt(totals.diamonds)} sub={`${groups.length} 個${dimLabel}`} />
        <Kpi label="有收益主播" value={<>{totals.earning}<small> / {rows.length}</small></>} sub={`活躍率 ${fmtPct(totals.earning / rows.length)}`} />
        <Kpi label="直播總時數" value={fmtHr(totals.hours) + ' h'} sub={`新人加入 ${totals.rookie} 位`} />
        <Kpi label="違規主播" value={totals.violative} sub={totals.violative ? '需人工複核' : '本期無違規'} />
      </section>

      <section className="grid-2">
        <div className="card">
          <div className="card-head"><h3>獎金組成</h3><span className="muted">Estimated bonus breakdown</span></div>
          <BonusBreakdown rows={rows} />
        </div>
        <div className="card">
          <div className="card-head"><h3>對帳進度</h3><span className="muted">依{dimLabel}</span></div>
          <div className="progress">
            <div className="stack stack-thin">
              {statusCounts.filter((s) => s.n).map((s) => <div key={s.v} className={'stack-seg st-' + s.v} style={{ flexGrow: s.n }} />)}
            </div>
            <div className="progress-grid">
              {statusCounts.map((s) => (
                <div key={s.v} className="progress-cell">
                  <span className={'pill-dot st-' + s.v} />
                  <span>{s.label}</span>
                  <b className="num">{s.n}</b>
                </div>
              ))}
            </div>
          </div>
        </div>
      </section>

      <section className="card card-flush">
        <div className="card-head pad">
          <h3>{dimLabel}對帳彙總</h3>
          <div className="seg">
            {DIMENSIONS.map((d) => <button key={d.key} className={dim === d.key ? 'on' : ''} onClick={() => setDim(d.key)}>{d.label}</button>)}
          </div>
          <div className="spacer" />
          <button className="btn ghost" onClick={exportAgg}>匯出 CSV</button>
        </div>
        <div className="table-wrap">
          <table className="tbl">
            <thead>
              <tr>
                <SortTh k="name" sort={sort} setSort={setSort}>{dimLabel}</SortTh>
                <SortTh k="count" sort={sort} setSort={setSort} align="r">主播數</SortTh>
                <SortTh k="earning" sort={sort} setSort={setSort} align="r">有收益</SortTh>
                <SortTh k="diamonds" sort={sort} setSort={setSort} align="r">鑽石</SortTh>
                <SortTh k="hours" sort={sort} setSort={setSort} align="r">直播時數</SortTh>
                <SortTh k="bonus" sort={sort} setSort={setSort} align="r">預估獎金</SortTh>
                <SortTh k="payout" sort={sort} setSort={setSort} align="r">應付 USD</SortTh>
                <SortTh k="payoutTWD" sort={sort} setSort={setSort} align="r">匯款 TWD</SortTh>
                <th className="share-col">佔比</th>
                <th>狀態</th>
                <th></th>
              </tr>
            </thead>
            <tbody>
              {groups.map((g) => {
                const key = `${month}|${dim}|${g.name}`;
                return (
                  <tr key={g.name} className="clickable" onClick={() => openStatement(g.name)}>
                    <td><span className="name">{g.name || <i className="muted">(未指定)</i>}</span>{g.violative > 0 && <span className="flag">違規 {g.violative}</span>}</td>
                    <td className="r num">{g.count}</td>
                    <td className="r num">{g.earning}</td>
                    <td className="r num">{fmtInt(g.diamonds)}</td>
                    <td className="r num">{fmtHr(g.hours)}</td>
                    <td className="r num">{fmtMoney(g.bonus)}</td>
                    <td className="r num">{fmtMoney(g.payout)}</td>
                    <td className="r num strong payout">{fmtTWD(g.payoutTWD)}</td>
                    <td className="share-col"><div className="bar"><i style={{ width: (g.payout / maxBonus) * 100 + '%' }} /></div><span className="num muted">{fmtPct(g.payout / (totals.payout || 1))}</span></td>
                    <td><StatusPill value={status[key]} onChange={(v) => setStatus(key, v)} /></td>
                    <td className="r"><span className="link">對帳單 →</span></td>
                  </tr>
                );
              })}
            </tbody>
            <tfoot>
              <tr>
                <td>合計</td>
                <td className="r num">{rows.length}</td>
                <td className="r num">{totals.earning}</td>
                <td className="r num">{fmtInt(totals.diamonds)}</td>
                <td className="r num">{fmtHr(totals.hours)}</td>
                <td className="r num">{fmtMoney(totals.bonus)}</td>
                <td className="r num">{fmtMoney(totals.payout)}</td>
                <td className="r num strong payout">{fmtTWD(totals.payoutTWD)}</td>
                <td colSpan={3}></td>
              </tr>
            </tfoot>
          </table>
        </div>
      </section>
    </div>
  );
}

// ---------- Creators ----------
const PAGE = 50;
function CreatorsView({ rows, month, onPick, initialAgent, toggleGuild }) {
  const [q, setQ] = React.useState('');
  const [agent, setAgent] = React.useState(initialAgent || '');
  const [onlyEarning, setOnlyEarning] = React.useState(true);
  const [onlyViol, setOnlyViol] = React.useState(false);
  const [sort, setSort] = React.useState({ k: 'bonus', dir: 'desc' });
  const [page, setPage] = React.useState(0);
  React.useEffect(() => { if (initialAgent != null) setAgent(initialAgent); }, [initialAgent]);
  React.useEffect(() => setPage(0), [q, agent, onlyEarning, onlyViol, sort, month]);

  const agents = React.useMemo(() => [...new Set(rows.map((r) => r.agent))].sort((a, b) => a.localeCompare(b, 'zh-Hant')), [rows]);
  const filtered = React.useMemo(() => {
    const s = q.trim().toLowerCase();
    return sortRows(rows.filter((r) =>
      (!agent || r.agent === agent) && (!onlyEarning || r.diamonds > 0) && (!onlyViol || r.violative) &&
      (!s || r.nick.toLowerCase().includes(s) || r.handle.toLowerCase().includes(s) || r.id.includes(s))
    ), sort);
  }, [rows, q, agent, onlyEarning, onlyViol, sort]);
  const pages = Math.max(1, Math.ceil(filtered.length / PAGE));
  const slice = filtered.slice(page * PAGE, page * PAGE + PAGE);

  const exportCSV = () => downloadCSV(`主播明細_${month}${agent ? '_' + agent : ''}.csv`,
    ['Creator ID', '暱稱', 'Handle', '經紀人', '群組', '群組經理', '違規', '新人', '鑽石', '有效天數', '直播時數', '預估獎金', '分潤類型', '分潤比例', '應付分潤 USD', '匯款 TWD', ...BONUS_PARTS.map((p) => p.label)],
    filtered.map((r) => [r.id, r.nick, r.handle, r.agent, r.group, r.gm, r.violative ? 'Y' : '', r.rookie ? 'Y' : '', r.diamonds, r.days, r.hours, r.bonus, r.shareType, r.shareRate + '%', r.payout, r.payoutTWD, ...BONUS_PARTS.map((p) => r[p.key] ?? '')]));

  return (
    <div className="view">
      <section className="card card-flush">
        <div className="toolbar pad">
          <div className="search">
            <svg width="14" height="14" viewBox="0 0 16 16"><circle cx="7" cy="7" r="5" fill="none" stroke="currentColor" strokeWidth="1.6" /><path d="M11 11l3.5 3.5" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" /></svg>
            <input value={q} onChange={(e) => setQ(e.target.value)} placeholder="搜尋暱稱、Handle 或 Creator ID" />
          </div>
          <select className="select" value={agent} onChange={(e) => setAgent(e.target.value)}>
            <option value="">全部經紀人</option>
            {agents.map((a) => <option key={a} value={a}>{a}</option>)}
          </select>
          <label className="check"><input type="checkbox" checked={onlyEarning} onChange={(e) => setOnlyEarning(e.target.checked)} />僅顯示有收益</label>
          <label className="check"><input type="checkbox" checked={onlyViol} onChange={(e) => setOnlyViol(e.target.checked)} />僅違規</label>
          <div className="spacer" />
          <span className="muted num">{filtered.length} 筆</span>
          <button className="btn ghost" onClick={exportCSV}>匯出 CSV</button>
        </div>
        <div className="table-wrap">
          <table className="tbl">
            <thead>
              <tr>
                <SortTh k="nick" sort={sort} setSort={setSort}>主播</SortTh>
                <SortTh k="agent" sort={sort} setSort={setSort}>經紀人 / 群組</SortTh>
                <SortTh k="diamonds" sort={sort} setSort={setSort} align="r">鑽石</SortTh>
                <SortTh k="days" sort={sort} setSort={setSort} align="r">有效天數</SortTh>
                <SortTh k="hours" sort={sort} setSort={setSort} align="r">直播時數</SortTh>
                <SortTh k="bonus" sort={sort} setSort={setSort} align="r">預估獎金</SortTh>
                <SortTh k="shareRate" sort={sort} setSort={setSort}>分潤</SortTh>
                <SortTh k="payout" sort={sort} setSort={setSort} align="r">應付</SortTh>
                <th>獎金組成</th>
                <th></th>
              </tr>
            </thead>
            <tbody>
              {slice.map((r) => (
                <tr key={r.id} className="clickable" onClick={() => onPick(r)}>
                  <td>
                    <div className="creator">
                      <span className="name">{r.nick}</span>
                      <span className="handle">@{r.handle}{r.rookie && <b className="tag">新人</b>}{r.violative && <b className="tag tag-red">違規</b>}</span>
                    </div>
                  </td>
                  <td><div className="creator"><span>{r.agent}</span><span className="handle">{r.group || '—'}</span></div></td>
                  <td className="r num">{fmtInt(r.diamonds)}</td>
                  <td className="r num">{r.days}</td>
                  <td className="r num">{fmtHr(r.hours)}</td>
                  <td className="r num">{fmtMoney(r.bonus)}</td>
                  <td><ShareBadge r={r} /></td>
                  <td className="r num"><div className="creator" style={{ alignItems: 'flex-end' }}><b className="payout">{fmtTWD(r.payoutTWD)}</b><span className="handle">{fmtMoney(r.payout)}</span></div></td>
                  <td><MiniStack r={r} /></td>
                  <td className="r"><button className={'guild-btn' + (r.guild ? ' on' : '')} onClick={(e) => { e.stopPropagation(); toggleGuild(r.id); }}>{r.guild ? '公會代運營 ✓' : '標記公會'}</button></td>
                </tr>
              ))}
              {!slice.length && <tr><td colSpan={10} className="empty">沒有符合條件的主播</td></tr>}
            </tbody>
          </table>
        </div>
        {pages > 1 && (
          <div className="pager pad">
            <button className="btn ghost" disabled={page === 0} onClick={() => setPage(page - 1)}>上一頁</button>
            <span className="num muted">{page + 1} / {pages}</span>
            <button className="btn ghost" disabled={page >= pages - 1} onClick={() => setPage(page + 1)}>下一頁</button>
          </div>
        )}
      </section>
    </div>
  );
}

function MiniStack({ r }) {
  const parts = BONUS_PARTS.map((p) => ({ ...p, v: r[p.key] || 0 })).filter((p) => p.v > 0);
  if (!parts.length) return <span className="muted">—</span>;
  return (
    <div className="stack stack-mini" title={parts.map((p) => `${p.label} ${fmtMoney(p.v)}`).join('\n')}>
      {parts.map((p) => <div key={p.key} className="stack-seg" style={{ flexGrow: p.v, background: p.color }} />)}
    </div>
  );
}

function CreatorDrawer({ r, onClose, toggleGuild }) {
  React.useEffect(() => {
    const h = (e) => e.key === 'Escape' && onClose();
    window.addEventListener('keydown', h); return () => window.removeEventListener('keydown', h);
  }, []);
  if (!r) return null;
  const Row = ({ k, v }) => <div className="kv"><span>{k}</span><b className="num">{v}</b></div>;
  return (
    <div className="drawer-scrim" onClick={onClose}>
      <aside className="drawer" onClick={(e) => e.stopPropagation()}>
        <div className="drawer-head">
          <div>
            <div className="drawer-title">{r.nick}</div>
            <div className="handle">@{r.handle} · <span className="num">{r.id}</span></div>
          </div>
          <button className="icon-btn" onClick={onClose} aria-label="關閉">✕</button>
        </div>
        <div className="drawer-tags">
          {r.rookie && <b className="tag">加入時為新人</b>}
          {r.violative && <b className="tag tag-red">違規主播</b>}
        </div>
        <div className="drawer-total">
          <div><span>應付匯款 (TWD)</span><div className="num" style={{ fontSize: 12, color: '#b5c2bd', marginTop: 2 }}>{fmtMoney(r.bonus)} × {r.shareRate}% = {fmtMoney(r.payout)}</div><div className="num" style={{ fontSize: 12, color: '#b5c2bd' }}>× 匯率 {window.RECON_FX}（{r.shareType}）</div></div>
          <b className="num">{fmtTWD(r.payoutTWD)}</b>
        </div>
        <button className={'guild-btn' + (r.guild ? ' on' : '')} onClick={() => toggleGuild(r.id)}>{r.guild ? '公會代運營 ✓（點擊取消）' : '標記為公會代運營'}</button>
        <div className="drawer-sec">
          <h4>歸屬</h4>
          <Row k="經紀人" v={r.agent || '—'} />
          <Row k="群組" v={r.group || '—'} />
          <Row k="群組經理" v={r.gm || '—'} />
        </div>
        <div className="drawer-sec">
          <h4>直播表現</h4>
          <Row k="鑽石" v={fmtInt(r.diamonds)} />
          <Row k="有效天數" v={r.days + ' 天'} />
          <Row k="直播時數" v={fmtHr(r.hours) + ' h'} />
        </div>
        <div className="drawer-sec">
          <h4>獎金明細</h4>
          {BONUS_PARTS.map((p) => (
            <div className="kv" key={p.key}>
              <span><i className="dot" style={{ background: p.color }} />{p.label}</span>
              <b className={'num' + (!r[p.key] ? ' muted' : '')}>{fmtMoney(r[p.key] || 0)}</b>
            </div>
          ))}
          <div className="kv"><span className="muted">　增量收益計算</span><b className="num muted">{fmtInt(r.diamonds)} × {window.RECON_RATE}%（平台值 {fmtMoney(r.bIncrPlatform)}）</b></div>
          <div className="kv"><span>站外主播任務</span><b className="muted">{r.bOff == null ? '未參加' : fmtMoney(r.bOff)}</b></div>
          <div className="kv"><span>站外主播任務 (2026.3)</span><b className="muted">{r.bOff263 == null ? '未參加' : fmtMoney(r.bOff263)}</b></div>
        </div>
      </aside>
    </div>
  );
}

Object.assign(window, { OverviewView, CreatorsView, CreatorDrawer, StatusPill, MiniStack, sortRows });
