import { useCallback, useEffect, useRef, useState } from 'react';
import {
  cancelUserSubscription,
  createSubscriptionPlan,
  deleteSubscriptionPlan,
  grantUserSubscription,
  listAdminLedger,
  listAdminSubscriptions,
  listAdminUsage,
  listSubscriptionPlans,
  rechargeUser,
  syncSubscriptionPlansToProduction,
  updateSubscriptionPlan,
} from '../../api/client';
import type { PagedResult } from '../../api/client';
import type { AdminSubscription, AdminUserRow, LedgerEntry, PlanDefinition, UsageRecord } from '../../types';
import { Pagination } from '../../components/Pagination';
import { useAdminUsers } from '../hooks/useAdminUsers';
import { formatTime, formatYuan } from '../utils/format';

function UserCombobox({
  users,
  value,
  onChange,
  placeholder = '搜索用户名 / 显示名称',
}: {
  users: AdminUserRow[];
  value: string;
  onChange: (id: string) => void;
  placeholder?: string;
}) {
  const [query, setQuery] = useState('');
  const [open, setOpen] = useState(false);
  const ref = useRef<HTMLDivElement>(null);

  const selected = users.find((u) => u.id === value);

  const filtered = query.trim()
    ? users.filter((u) => {
        const q = query.toLowerCase();
        return u.username.toLowerCase().includes(q) || u.displayName.toLowerCase().includes(q);
      })
    : users;

  useEffect(() => {
    const handler = (e: MouseEvent) => {
      if (ref.current && !ref.current.contains(e.target as Node)) setOpen(false);
    };
    document.addEventListener('mousedown', handler);
    return () => document.removeEventListener('mousedown', handler);
  }, []);

  const select = (u: AdminUserRow) => {
    onChange(u.id);
    setQuery('');
    setOpen(false);
  };

  const clear = () => {
    onChange('');
    setQuery('');
  };

  return (
    <div ref={ref} className="user-combobox">
      <div className="user-combobox-input-wrap" onClick={() => setOpen(true)}>
        {selected && !open ? (
          <span className="user-combobox-selected">
            {selected.displayName} <span className="muted">@{selected.username}</span>
            <span className="user-combobox-balance">¥{formatYuan(selected.balanceCents)}</span>
          </span>
        ) : (
          <input
            className="user-combobox-input"
            placeholder={selected ? `${selected.displayName} @${selected.username}` : placeholder}
            value={query}
            autoFocus={open}
            onChange={(e) => { setQuery(e.target.value); setOpen(true); }}
            onFocus={() => setOpen(true)}
          />
        )}
        {value && (
          <button type="button" className="user-combobox-clear" onClick={(e) => { e.stopPropagation(); clear(); }}>×</button>
        )}
      </div>
      {open && (
        <div className="user-combobox-dropdown">
          {filtered.length === 0 ? (
            <div className="user-combobox-empty">无匹配用户</div>
          ) : (
            filtered.map((u) => (
              <div key={u.id} className="user-combobox-option" onMouseDown={() => select(u)}>
                <span className="user-combobox-name">{u.displayName}</span>
                <span className="user-combobox-meta muted">@{u.username}</span>
                <span className="user-combobox-bal">¥{formatYuan(u.balanceCents)}</span>
              </div>
            ))
          )}
        </div>
      )}
    </div>
  );
}

type TabKey = 'recharge' | 'usage' | 'ledger' | 'subscriptions';

const TABS: { key: TabKey; label: string }[] = [
  { key: 'subscriptions', label: '订阅记录' },
  { key: 'recharge', label: '充值' },
  { key: 'usage', label: '用量记录' },
  { key: 'ledger', label: '资金流水' },
];

const PAGE_SIZE = 20;

function RechargeTab() {
  const { users, reload, error, setError } = useAdminUsers();
  const [message, setMessage] = useState<string | null>(null);
  const [recharge, setRecharge] = useState({ userId: '', amountYuan: '10', note: '' });
  const [submitting, setSubmitting] = useState(false);

  const handleRecharge = async (e: React.FormEvent) => {
    e.preventDefault();
    if (!recharge.userId) return;
    setMessage(null);
    setError(null);
    setSubmitting(true);
    try {
      const amountCents = Math.round(Number(recharge.amountYuan) * 100);
      await rechargeUser(recharge.userId, amountCents, recharge.note || undefined);
      setMessage('充值成功');
      setRecharge((s) => ({ ...s, userId: '', note: '' }));
      await reload();
    } catch (err) {
      setError(err instanceof Error ? err.message : '充值失败');
    } finally {
      setSubmitting(false);
    }
  };

  return (
    <section className="admin-card">
      <h2>充值</h2>
      {error && <p className="banner banner-error">{error}</p>}
      {message && <p className="banner banner-info">{message}</p>}
      <form className="admin-form" onSubmit={handleRecharge}>
        <UserCombobox
          users={users.filter((u) => u.role === 'user')}
          value={recharge.userId}
          onChange={(id) => setRecharge((s) => ({ ...s, userId: id }))}
        />
        <input placeholder="金额（元）" type="number" min="0.01" step="0.01" value={recharge.amountYuan}
          onChange={(e) => setRecharge((s) => ({ ...s, amountYuan: e.target.value }))} />
        <input placeholder="备注（可选）" value={recharge.note}
          onChange={(e) => setRecharge((s) => ({ ...s, note: e.target.value }))} />
        <button type="submit" className="send-btn" disabled={!recharge.userId || submitting}>
          {submitting ? '处理中…' : '充值'}
        </button>
      </form>
    </section>
  );
}

function UsageTab() {
  const { users } = useAdminUsers();
  const [result, setResult] = useState<PagedResult<UsageRecord> | null>(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [filterUserId, setFilterUserId] = useState('');
  const [pendingUserId, setPendingUserId] = useState('');

  const load = useCallback(async (p: number, userId: string) => {
    setLoading(true);
    setError(null);
    try {
      const data = await listAdminUsage({ userId: userId || undefined, page: p, pageSize: PAGE_SIZE });
      setResult(data);
      setFilterUserId(userId);
    } catch (err) {
      setError(err instanceof Error ? err.message : '加载失败');
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => { void load(1, ''); }, [load]);

  const handleQuery = () => void load(1, pendingUserId);
  const handlePage = (p: number) => void load(p, filterUserId);

  return (
    <section className="admin-card">
      <div className="admin-card-head">
        <h2>用量记录</h2>
        <div className="billing-toolbar">
          <UserCombobox
            users={users}
            value={pendingUserId}
            onChange={setPendingUserId}
            placeholder="全部用户"
          />
          <button type="button" className="send-btn billing-query-btn" onClick={handleQuery} disabled={loading}>
            查询
          </button>
        </div>
      </div>
      {error && <p className="banner banner-error">{error}</p>}
      {!result && !loading && (
        <p className="muted billing-empty">选择筛选条件后点击查询</p>
      )}
      {loading && <p className="muted">加载中…</p>}
      {!loading && result && (
        result.items.length === 0 ? (
          <p className="muted billing-empty">暂无记录</p>
        ) : (
          <>
            <div className="admin-table-wrap">
              <table className="admin-table">
                <thead>
                  <tr>
                    <th>时间</th>
                    <th>用户</th>
                    <th style={{ textAlign: 'right' }}>输入 Token</th>
                    <th style={{ textAlign: 'right' }}>输出 Token</th>
                    <th style={{ textAlign: 'right' }}>扣费</th>
                    <th style={{ textAlign: 'right' }}>余额后</th>
                  </tr>
                </thead>
                <tbody>
                  {result.items.map((row) => (
                    <tr key={row.id}>
                      <td className="billing-time">{formatTime(row.createdAt)}</td>
                      <td>@{row.username}</td>
                      <td className="billing-num">{row.inputTokens.toLocaleString()}</td>
                      <td className="billing-num">{row.outputTokens.toLocaleString()}</td>
                      <td className="billing-num">¥{formatYuan(row.costCents)}</td>
                      <td className="billing-num">¥{formatYuan(row.balanceAfterCents)}</td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
            <Pagination page={result.page} totalPages={result.totalPages} total={result.total}
              pageSize={result.pageSize} onChange={handlePage} />
          </>
        )
      )}
    </section>
  );
}

function LedgerTab() {
  const { users } = useAdminUsers();
  const [result, setResult] = useState<PagedResult<LedgerEntry> | null>(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [filterUserId, setFilterUserId] = useState('');
  const [pendingUserId, setPendingUserId] = useState('');

  const load = useCallback(async (p: number, userId: string) => {
    setLoading(true);
    setError(null);
    try {
      const data = await listAdminLedger({ userId: userId || undefined, page: p, pageSize: PAGE_SIZE });
      setResult(data);
      setFilterUserId(userId);
    } catch (err) {
      setError(err instanceof Error ? err.message : '加载失败');
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => { void load(1, ''); }, [load]);

  const handleQuery = () => void load(1, pendingUserId);
  const handlePage = (p: number) => void load(p, filterUserId);

  const TYPE_LABEL: Record<string, string> = { recharge: '充值', deduct: '扣费', refund: '退款', adjust: '调整' };

  return (
    <section className="admin-card">
      <div className="admin-card-head">
        <h2>资金流水</h2>
        <div className="billing-toolbar">
          <UserCombobox
            users={users}
            value={pendingUserId}
            onChange={setPendingUserId}
            placeholder="全部用户"
          />
          <button type="button" className="send-btn billing-query-btn" onClick={handleQuery} disabled={loading}>
            查询
          </button>
        </div>
      </div>
      {error && <p className="banner banner-error">{error}</p>}
      {!result && !loading && (
        <p className="muted billing-empty">选择筛选条件后点击查询</p>
      )}
      {loading && <p className="muted">加载中…</p>}
      {!loading && result && (
        result.items.length === 0 ? (
          <p className="muted billing-empty">暂无记录</p>
        ) : (
          <>
            <div className="admin-table-wrap">
              <table className="admin-table">
                <thead>
                  <tr>
                    <th>时间</th>
                    <th>用户</th>
                    <th>类型</th>
                    <th style={{ textAlign: 'right' }}>金额</th>
                    <th>备注</th>
                  </tr>
                </thead>
                <tbody>
                  {result.items.map((row) => (
                    <tr key={row.id}>
                      <td className="billing-time">{formatTime(row.createdAt)}</td>
                      <td>@{row.username}</td>
                      <td><span className={`ledger-type-tag ledger-type-${row.type}`}>{TYPE_LABEL[row.type] ?? row.type}</span></td>
                      <td className={`billing-num ${row.amountCents < 0 ? 'text-error' : 'text-income'}`}>
                        {row.amountCents >= 0 ? '+' : ''}¥{formatYuan(Math.abs(row.amountCents))}
                      </td>
                      <td className="billing-note">{row.note ?? '—'}</td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
            <Pagination page={result.page} totalPages={result.totalPages} total={result.total}
              pageSize={result.pageSize} onChange={handlePage} />
          </>
        )
      )}
    </section>
  );
}

const PLAN_TIER_LABEL: Record<string, string> = {
  basic: '基础',
  standard: '标准',
  premium: '旗舰',
};

const EMPTY_PLAN_FORM = {
  planType: '',
  name: '',
  priceCents: '0',
  periodDays: '30',
  periodTokens: '0',
  periodImages: '0',
  modelTier: 'basic',
  overageRate: '1.00',
  sortOrder: '0',
  isActive: true,
  description: '',
};

type PlanForm = typeof EMPTY_PLAN_FORM;

function planToForm(p: PlanDefinition): PlanForm {
  return {
    planType: p.planType,
    name: p.name,
    priceCents: String(p.priceCents),
    periodDays: String(p.periodDays),
    periodTokens: String(p.periodTokens),
    periodImages: String(p.periodImages),
    modelTier: p.modelTier,
    overageRate: String(p.overageRate),
    sortOrder: String(p.sortOrder),
    isActive: p.isActive,
    description: p.description ?? '',
  };
}

function PlanFormModal({
  initial,
  onSave,
  onClose,
}: {
  initial: PlanForm;
  onSave: (form: PlanForm) => Promise<void>;
  onClose: () => void;
}) {
  const [form, setForm] = useState<PlanForm>(initial);
  const [saving, setSaving] = useState(false);
  const [err, setErr] = useState<string | null>(null);
  const isNew = !initial.planType;

  const set = (key: keyof PlanForm, val: string | boolean) =>
    setForm((s) => ({ ...s, [key]: val }));

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    setSaving(true);
    setErr(null);
    try {
      await onSave(form);
    } catch (ex) {
      setErr(ex instanceof Error ? ex.message : '保存失败');
    } finally {
      setSaving(false);
    }
  };

  return (
    <div className="modal-backdrop" onClick={(e) => e.target === e.currentTarget && onClose()}>
      <div className="modal-box" style={{ maxWidth: 520 }}>
        <div className="modal-head">
          <h3>{isNew ? '新建套餐' : `编辑套餐 · ${initial.name}`}</h3>
          <button type="button" className="modal-close" onClick={onClose}>×</button>
        </div>
        {err && <p className="banner banner-error">{err}</p>}
        <form className="admin-form plan-form" onSubmit={handleSubmit}>
          {isNew && (
            <label className="plan-form-row">
              <span>套餐标识 <span className="muted">(plan_type)</span></span>
              <input
                placeholder="如 basic / pro_plus"
                value={form.planType}
                onChange={(e) => set('planType', e.target.value.toLowerCase().replace(/[^a-z0-9_]/g, ''))}
                required
              />
            </label>
          )}
          <label className="plan-form-row">
            <span>显示名称</span>
            <input placeholder="如 专业版" value={form.name} onChange={(e) => set('name', e.target.value)} required />
          </label>
          <label className="plan-form-row">
            <span>月价格（分）</span>
            <input type="number" min="0" step="1" value={form.priceCents}
              onChange={(e) => set('priceCents', e.target.value)} />
            <span className="plan-form-hint">¥{(Number(form.priceCents) / 100).toFixed(2)} / 月</span>
          </label>
          <label className="plan-form-row">
            <span>有效天数</span>
            <input type="number" min="1" step="1" value={form.periodDays}
              onChange={(e) => set('periodDays', e.target.value)} />
          </label>
          <label className="plan-form-row">
            <span>Token 配额</span>
            <input type="number" min="0" step="10000" value={form.periodTokens}
              onChange={(e) => set('periodTokens', e.target.value)} />
            <span className="plan-form-hint">
              {Number(form.periodTokens) === 0 ? '不限' : `${(Number(form.periodTokens) / 10000).toFixed(0)} 万 Token`}
            </span>
          </label>
          <label className="plan-form-row">
            <span>图片配额（张）</span>
            <input type="number" min="0" step="1" value={form.periodImages}
              onChange={(e) => set('periodImages', e.target.value)} />
            <span className="plan-form-hint">
              {Number(form.periodImages) === 0 ? '不限' : `${form.periodImages} 张/周期`}
            </span>
          </label>
          <label className="plan-form-row">
            <span>模型层级</span>
            <select className="admin-select" value={form.modelTier}
              onChange={(e) => set('modelTier', e.target.value)}>
              <option value="basic">基础（basic）</option>
              <option value="standard">标准（standard）</option>
              <option value="premium">旗舰（premium）</option>
            </select>
          </label>
          <label className="plan-form-row">
            <span>超量费率</span>
            <input type="number" min="0" max="2" step="0.01" value={form.overageRate}
              onChange={(e) => set('overageRate', e.target.value)} />
            <span className="plan-form-hint">配额耗尽后的费用倍率（1.0 = 正常价格）</span>
          </label>
          <label className="plan-form-row">
            <span>排序权重</span>
            <input type="number" step="1" value={form.sortOrder}
              onChange={(e) => set('sortOrder', e.target.value)} />
          </label>
          <label className="plan-form-row">
            <span>简介（可选）</span>
            <input placeholder="套餐说明文字" value={form.description}
              onChange={(e) => set('description', e.target.value)} />
          </label>
          <label className="plan-form-row plan-form-check">
            <input type="checkbox" checked={form.isActive}
              onChange={(e) => set('isActive', e.target.checked)} />
            <span>对用户可见（上架）</span>
          </label>
          <div className="plan-form-actions">
            <button type="button" className="admin-btn-secondary" onClick={onClose}>取消</button>
            <button type="submit" className="send-btn" disabled={saving}>
              {saving ? '保存中…' : '保存套餐'}
            </button>
          </div>
        </form>
      </div>
    </div>
  );
}

function PlanCatalogSection({
  plans,
  onPlansChange,
}: {
  plans: PlanDefinition[];
  onPlansChange: () => void;
}) {
  const [editing, setEditing] = useState<PlanForm | null>(null);
  const [err, setErr] = useState<string | null>(null);
  const [msg, setMsg] = useState<string | null>(null);
  const [deleting, setDeleting] = useState<string | null>(null);
  const [syncingProd, setSyncingProd] = useState(false);

  const openNew = () => setEditing({ ...EMPTY_PLAN_FORM });
  const openEdit = (p: PlanDefinition) => setEditing(planToForm(p));
  const closeModal = () => setEditing(null);

  const handleSave = async (form: PlanForm) => {
    const data = {
      name: form.name,
      priceCents: Number(form.priceCents),
      periodDays: Number(form.periodDays),
      periodTokens: Number(form.periodTokens),
      periodImages: Number(form.periodImages),
      modelTier: form.modelTier,
      overageRate: Number(form.overageRate),
      sortOrder: Number(form.sortOrder),
      isActive: form.isActive,
      description: form.description || null,
    };
    const isNew = !editing?.planType || editing.planType !== form.planType;
    if (isNew) {
      const result = await createSubscriptionPlan(form.planType, data);
      setMsg(
        result.sync?.ok === false
          ? `已创建套餐「${form.name}」，但生产后台同步失败：${result.sync.message}`
          : result.sync?.message
            ? `已创建套餐「${form.name}」，${result.sync.message}`
            : `已创建套餐「${form.name}」`,
      );
    } else {
      const result = await updateSubscriptionPlan(form.planType, data);
      setMsg(
        result.sync?.ok === false
          ? `已更新套餐「${form.name}」，但生产后台同步失败：${result.sync.message}`
          : result.sync?.message
            ? `已更新套餐「${form.name}」，${result.sync.message}`
            : `已更新套餐「${form.name}」`,
      );
    }
    closeModal();
    onPlansChange();
  };

  const handleDelete = async (p: PlanDefinition) => {
    if (!window.confirm(`确认删除套餐「${p.name}」？已购用户不受影响，但新用户无法选择此套餐。`)) return;
    setDeleting(p.planType);
    setErr(null);
    try {
      const result = await deleteSubscriptionPlan(p.planType);
      setMsg(
        result.sync?.ok === false
          ? `已删除套餐「${p.name}」，但生产后台同步失败：${result.sync.message}`
          : result.sync?.message
            ? `已删除套餐「${p.name}」，${result.sync.message}`
            : `已删除套餐「${p.name}」`,
      );
      onPlansChange();
    } catch (ex) {
      setErr(ex instanceof Error ? ex.message : '删除失败');
    } finally {
      setDeleting(null);
    }
  };

  const handleSyncProduction = async () => {
    setSyncingProd(true);
    setErr(null);
    try {
      const result = await syncSubscriptionPlansToProduction();
      if (result.ok) setMsg(result.message);
      else setErr(result.message);
    } catch (ex) {
      setErr(ex instanceof Error ? ex.message : '同步生产后台失败');
    } finally {
      setSyncingProd(false);
    }
  };

  return (
    <section className="admin-card">
      <div className="admin-card-head">
        <h2>套餐目录</h2>
        <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
          <button type="button" className="admin-btn-secondary" onClick={handleSyncProduction} disabled={syncingProd}>
            {syncingProd ? '同步中…' : '同步生产后台'}
          </button>
          <button type="button" className="send-btn" onClick={openNew}>+ 新建套餐</button>
        </div>
      </div>
      {err && <p className="banner banner-error">{err}</p>}
      {msg && <p className="banner banner-info">{msg}</p>}
      {plans.length === 0 ? (
        <p className="muted">暂无套餐，点击「新建套餐」添加。</p>
      ) : (
        <div className="admin-table-wrap">
          <table className="admin-table">
            <thead>
              <tr>
                <th>套餐</th>
                <th style={{ textAlign: 'right' }}>价格</th>
                <th style={{ textAlign: 'right' }}>Token 配额</th>
                <th style={{ textAlign: 'right' }}>图片配额</th>
                <th>模型层级</th>
                <th>天数</th>
                <th>超量费率</th>
                <th>状态</th>
                <th></th>
              </tr>
            </thead>
            <tbody>
              {plans.map((p) => (
                <tr key={p.planType} style={{ opacity: p.isActive ? 1 : 0.5 }}>
                  <td>
                    <strong>{p.name}</strong>
                    <span className="muted"> ({p.planType})</span>
                    {p.description && <div className="plan-desc muted">{p.description}</div>}
                  </td>
                  <td className="billing-num">
                    {p.priceCents === 0 ? '免费' : `¥${formatYuan(p.priceCents)}/月`}
                  </td>
                  <td className="billing-num">
                    {p.periodTokens === 0 ? '不限' : `${(p.periodTokens / 10000).toFixed(0)} 万`}
                  </td>
                  <td className="billing-num">
                    {p.periodImages === 0 ? '不限' : `${p.periodImages} 张`}
                  </td>
                  <td>{PLAN_TIER_LABEL[p.modelTier] ?? p.modelTier}</td>
                  <td>{p.periodDays} 天</td>
                  <td>{p.overageRate === 1 ? '—' : `×${p.overageRate}`}</td>
                  <td>
                    <span className={`ledger-type-tag ledger-type-${p.isActive ? 'active' : 'cancelled'}`}>
                      {p.isActive ? '上架' : '下架'}
                    </span>
                  </td>
                  <td className="plan-actions">
                    <button type="button" className="admin-btn-secondary" onClick={() => openEdit(p)}>编辑</button>
                    {p.planType !== 'free' && (
                      <button type="button" className="admin-btn-danger"
                        disabled={deleting === p.planType}
                        onClick={() => void handleDelete(p)}>
                        {deleting === p.planType ? '删除中…' : '删除'}
                      </button>
                    )}
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      )}
      {editing !== null && (
        <PlanFormModal initial={editing} onSave={handleSave} onClose={closeModal} />
      )}
    </section>
  );
}

function SubscriptionsTab() {
  const { users, reload: reloadUsers } = useAdminUsers();
  const [plans, setPlans] = useState<PlanDefinition[]>([]);
  const [result, setResult] = useState<{
    items: AdminSubscription[];
    total: number;
    page: number;
    totalPages: number;
    pageSize: number;
  } | null>(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [message, setMessage] = useState<string | null>(null);
  const [filterUserId, setFilterUserId] = useState('');
  const [pendingUserId, setPendingUserId] = useState('');
  const [filterStatus, setFilterStatus] = useState('active');
  const [grant, setGrant] = useState({ userId: '', planType: '', durationDays: '', note: '' });
  const [submitting, setSubmitting] = useState(false);
  const [cancelling, setCancelling] = useState<string | null>(null);

  const loadPlans = useCallback(async () => {
    try {
      const p = await listSubscriptionPlans();
      setPlans(p);
    } catch { /* ignore */ }
  }, []);

  useEffect(() => { void loadPlans(); }, [loadPlans]);

  const load = useCallback(async (p: number, userId: string, status: string) => {
    setLoading(true);
    setError(null);
    try {
      const data = await listAdminSubscriptions({
        userId: userId || undefined,
        status: status || undefined,
        page: p,
        pageSize: 20,
      });
      setResult(data);
      setFilterUserId(userId);
      setFilterStatus(status);
    } catch (err) {
      setError(err instanceof Error ? err.message : '加载失败');
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => { void load(1, '', 'active'); }, [load]);

  const handleQuery = () => void load(1, pendingUserId, filterStatus);
  const handlePage = (p: number) => void load(p, filterUserId, filterStatus);

  const activePlans = plans.filter((p) => p.isActive && p.priceCents > 0);

  const handleGrant = async (e: React.FormEvent) => {
    e.preventDefault();
    if (!grant.userId || !grant.planType) return;
    setSubmitting(true);
    setError(null);
    setMessage(null);
    try {
      const days = grant.durationDays ? Number(grant.durationDays) : undefined;
      await grantUserSubscription(grant.userId, grant.planType, days, grant.note || undefined);
      const planName = plans.find((p) => p.planType === grant.planType)?.name ?? grant.planType;
      const user = users.find((u) => u.id === grant.userId);
      setMessage(`已为 ${user?.displayName ?? grant.userId} 授予 ${planName} 套餐`);
      setGrant((s) => ({ ...s, userId: '', note: '' }));
      await reloadUsers();
      void load(1, filterUserId, filterStatus);
    } catch (err) {
      setError(err instanceof Error ? err.message : '授予失败');
    } finally {
      setSubmitting(false);
    }
  };

  const handleCancel = async (userId: string, displayName: string) => {
    if (!window.confirm(`确认取消 ${displayName} 的套餐？`)) return;
    setCancelling(userId);
    setError(null);
    setMessage(null);
    try {
      await cancelUserSubscription(userId);
      setMessage(`已取消 ${displayName} 的套餐`);
      void load(1, filterUserId, filterStatus);
    } catch (err) {
      setError(err instanceof Error ? err.message : '取消失败');
    } finally {
      setCancelling(null);
    }
  };

  const STATUS_LABEL: Record<string, string> = { active: '有效', expired: '已到期', cancelled: '已取消' };

  return (
    <>
      <PlanCatalogSection plans={plans} onPlansChange={loadPlans} />

      {/* Grant subscription */}
      <section className="admin-card">
        <h2>授予套餐</h2>
        {error && <p className="banner banner-error">{error}</p>}
        {message && <p className="banner banner-info">{message}</p>}
        <form className="admin-form" onSubmit={handleGrant}>
          <UserCombobox
            users={users.filter((u) => u.role === 'user')}
            value={grant.userId}
            onChange={(id) => setGrant((s) => ({ ...s, userId: id }))}
          />
          <select
            className="admin-select"
            value={grant.planType}
            onChange={(e) => setGrant((s) => ({ ...s, planType: e.target.value }))}
            required
          >
            <option value="">选择套餐（含所有套餐）</option>
            {plans.map((p) => (
              <option key={p.planType} value={p.planType}>
                {p.name} — {p.priceCents === 0 ? '免费' : `¥${formatYuan(p.priceCents)}/月`}
                {!p.isActive ? ' [下架]' : ''}
              </option>
            ))}
          </select>
          <input
            placeholder="有效天数（留空用套餐默认）"
            type="number"
            min="1"
            value={grant.durationDays}
            onChange={(e) => setGrant((s) => ({ ...s, durationDays: e.target.value }))}
          />
          <input
            placeholder="备注（可选）"
            value={grant.note}
            onChange={(e) => setGrant((s) => ({ ...s, note: e.target.value }))}
          />
          <button type="submit" className="send-btn" disabled={!grant.userId || !grant.planType || submitting}>
            {submitting ? '处理中…' : '授予'}
          </button>
        </form>
      </section>

      {/* Subscription list */}
      <section className="admin-card">
        <div className="admin-card-head">
          <h2>订阅记录</h2>
          <div className="billing-toolbar">
            <UserCombobox
              users={users}
              value={pendingUserId}
              onChange={setPendingUserId}
              placeholder="全部用户"
            />
            <select
              className="admin-select billing-status-select"
              value={filterStatus}
              onChange={(e) => setFilterStatus(e.target.value)}
            >
              <option value="">全部状态</option>
              <option value="active">有效</option>
              <option value="expired">已到期</option>
              <option value="cancelled">已取消</option>
            </select>
            <button
              type="button"
              className="send-btn billing-query-btn"
              onClick={handleQuery}
              disabled={loading}
            >
              查询
            </button>
          </div>
        </div>
        {loading && <p className="muted">加载中…</p>}
        {!loading && result && (
          result.items.length === 0 ? (
            <p className="muted billing-empty">暂无记录</p>
          ) : (
            <>
              <div className="admin-table-wrap">
                <table className="admin-table">
                  <thead>
                    <tr>
                      <th>用户</th>
                      <th>套餐</th>
                      <th>状态</th>
                      <th style={{ textAlign: 'right' }}>Token 用量</th>
                      <th style={{ textAlign: 'right' }}>图片用量</th>
                      <th>到期时间</th>
                      <th>备注</th>
                      <th></th>
                    </tr>
                  </thead>
                  <tbody>
                    {result.items.map((row) => (
                      <tr key={row.id}>
                        <td>
                          <span>{row.displayName}</span>
                          <span className="muted"> @{row.username}</span>
                        </td>
                        <td><strong>{row.planType}</strong></td>
                        <td>
                          <span className={`ledger-type-tag ledger-type-${row.status}`}>
                            {STATUS_LABEL[row.status] ?? row.status}
                          </span>
                        </td>
                        <td className="billing-num">
                          {row.periodTokensUsed.toLocaleString()}
                          {row.periodTokensLimit > 0 && (
                            <span className="muted"> / {row.periodTokensLimit.toLocaleString()}</span>
                          )}
                        </td>
                        <td className="billing-num">
                          {row.periodImagesUsed}
                          {row.periodImagesLimit > 0 && (
                            <span className="muted"> / {row.periodImagesLimit}</span>
                          )}
                        </td>
                        <td className="billing-time">{formatTime(row.expiresAt)}</td>
                        <td className="billing-note">{row.note ?? '—'}</td>
                        <td>
                          {row.status === 'active' && (
                            <button
                              type="button"
                              className="admin-btn-danger"
                              disabled={cancelling === row.userId}
                              onClick={() => void handleCancel(row.userId, row.displayName)}
                            >
                              {cancelling === row.userId ? '取消中…' : '取消套餐'}
                            </button>
                          )}
                        </td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
              <Pagination
                page={result.page}
                totalPages={result.totalPages}
                total={result.total}
                pageSize={result.pageSize}
                onChange={handlePage}
              />
            </>
          )
        )}
      </section>
    </>
  );
}

export function BillingPage() {
  const [activeTab, setActiveTab] = useState<TabKey>('subscriptions');

  return (
    <div className="admin-page">
      <div className="admin-page-head">
        <h2>计费中心</h2>
        <p className="muted">充值、用量与资金流水</p>
      </div>
      <div className="admin-tabs" role="tablist">
        {TABS.map((tab) => (
          <button key={tab.key} type="button" role="tab" aria-selected={activeTab === tab.key}
            className={`admin-tab${activeTab === tab.key ? ' active' : ''}`}
            onClick={() => setActiveTab(tab.key)}>
            {tab.label}
          </button>
        ))}
      </div>
      <div className="billing-tab-content">
        {activeTab === 'recharge' && <RechargeTab />}
        {activeTab === 'usage' && <UsageTab />}
        {activeTab === 'ledger' && <LedgerTab />}
        {activeTab === 'subscriptions' && <SubscriptionsTab />}
      </div>
    </div>
  );
}
