// ===== page-admin.jsx =====
const { useState: useSA, useMemo: useMA, useEffect: useEA, useRef: useRA } = React;

const ADMIN_STATUSES = {
  pending:    { key: 'pending',    label: '待支付',          dotClass: 'bg-ink-400'   },
  uploaded:   { key: 'uploaded',   label: '已上传待确认',     dotClass: 'bg-warn-500'  },
  processing: { key: 'processing', label: 'LLM 处理中',      dotClass: 'bg-brand-500' },
  done:       { key: 'done',       label: '已完成',          dotClass: 'bg-ok-500'    },
  refunded:   { key: 'refunded',   label: '已退款',          dotClass: 'bg-bad-500'   },
  expired:    { key: 'expired',    label: '已过期',          dotClass: 'bg-ink-300'   },
  llm_failed: { key: 'llm_failed', label: 'LLM 失败',        dotClass: 'bg-bad-600'   },
};

// ⚠️ 后台凭证内嵌在前端（按需求降低使用门槛）。
// 一旦域名被公开广泛传播，请改回密码登录（注释掉下面 useEA 块即可）。
const ADMIN_AUTO_USERNAME = 'admin';
const ADMIN_AUTO_PASSWORD = 'JtrZvqHnvRprUtn5gLjg5nH_so4';

function AdminPage({ navigate }) {
  const [loggedIn, setLoggedIn] = useSA(window.API.isAdminLoggedIn());

  useEA(() => {
    if (!loggedIn) {
      window.API.saveAdmin(ADMIN_AUTO_USERNAME, ADMIN_AUTO_PASSWORD);
      setLoggedIn(true);
    }
  }, []);

  if (!loggedIn) {
    // 首次渲染瞬间的占位（自动登录会立刻完成）
    return (
      <div className="min-h-screen bg-ink-50 flex items-center justify-center">
        <I.Spinner size={28} className="text-brand-600" />
      </div>
    );
  }
  return <AdminDashboard onLogout={() => { window.API.clearAdmin(); setLoggedIn(false); window.location.hash = '#/'; }} navigate={navigate} />;
}

function AdminLogin({ onSuccess, navigate }) {
  const [username, setU] = useSA('admin');
  const [password, setP] = useSA('');
  const [submitting, setS] = useSA(false);
  const [error, setE] = useSA(null);

  const submit = async (e) => {
    e.preventDefault();
    if (!password.trim() || submitting) return;
    setS(true);
    setE(null);
    window.API.saveAdmin(username.trim(), password);
    try {
      await window.API.adminStats(); // 用 stats 端点验证凭证
      onSuccess();
    } catch (err) {
      window.API.clearAdmin();
      setE(err?.message || '登录失败');
    } finally {
      setS(false);
    }
  };

  return (
    <div className="min-h-screen bg-ink-50 flex items-center justify-center px-6">
      <Card className="w-full max-w-[420px] p-7">
        <div className="text-center">
          <I.Logo size={36} />
          <h1 className="mt-4 text-[22px] font-bold text-navy-900 tracking-tight">墨鉴管理后台</h1>
          <p className="mt-1 text-[12.5px] text-ink-500">仅限授权人员访问</p>
        </div>
        <form onSubmit={submit} className="mt-7 space-y-4">
          <div>
            <label className="text-[12px] font-medium text-ink-700">用户名</label>
            <input type="text" value={username} onChange={e => setU(e.target.value)} autoComplete="username"
                   className="mt-1 w-full h-10 px-3 rounded-lg ring-1 ring-ink-200 bg-white text-[13.5px] focus:outline-none focus:ring-2 focus:ring-brand-500" />
          </div>
          <div>
            <label className="text-[12px] font-medium text-ink-700">密码</label>
            <input type="password" value={password} onChange={e => setP(e.target.value)} autoComplete="current-password"
                   className="mt-1 w-full h-10 px-3 rounded-lg ring-1 ring-ink-200 bg-white text-[13.5px] focus:outline-none focus:ring-2 focus:ring-brand-500" />
          </div>
          {error && (
            <div className="text-[12px] text-bad-600 bg-bad-50 ring-1 ring-bad-100 rounded-md p-2 text-center">{error}</div>
          )}
          <Button kind="dark" size="lg" type="submit" disabled={submitting} className="w-full"
                  icon={submitting ? <I.Spinner size={14} /> : null}
                  iconRight={!submitting ? <I.ArrowRight size={14} /> : null}>
            {submitting ? '验证中...' : '登录'}
          </Button>
          <div className="text-center text-[12px] text-ink-500">
            <a onClick={() => navigate('home')} className="hover:text-navy-900 cursor-pointer">← 回到主站</a>
          </div>
        </form>
      </Card>
    </div>
  );
}

function AdminDashboard({ onLogout, navigate }) {
  const [orders, setOrders]       = useSA([]);
  const [total, setTotal]         = useSA(0);
  const [stats, setStats]         = useSA(null);
  const [loading, setLoading]     = useSA(true);
  const [q, setQ]                 = useSA('');
  const [statusFilter, setStatus] = useSA('all');
  const [busyId, setBusy]         = useSA(null);
  const [errMsg, setErrMsg]       = useSA(null);
  const refreshTimer = useRA(null);

  const load = async () => {
    try {
      const params = {};
      if (statusFilter !== 'all') params.status = statusFilter;
      if (q.trim()) {
        // 数字纯尾数搜索
        if (/^\d{1,2}$/.test(q.trim())) {
          params.amount_suffix = parseInt(q.trim(), 10);
        } else {
          params.q = q.trim();
        }
      }
      const [ord, st] = await Promise.all([
        window.API.adminListOrders(params),
        window.API.adminStats(),
      ]);
      setOrders(ord.items || []);
      setTotal(ord.total || 0);
      setStats(st);
      setErrMsg(null);
    } catch (err) {
      console.error('admin load failed', err);
      setErrMsg(err?.message || '加载失败');
      if (err?.status === 401) {
        onLogout();
      }
    } finally {
      setLoading(false);
    }
  };

  useEA(() => {
    load();
    refreshTimer.current = setInterval(load, 8000);
    return () => clearInterval(refreshTimer.current);
  }, [statusFilter, q]);

  const counts = useMA(() => {
    return Object.keys(ADMIN_STATUSES).reduce((acc, k) => {
      acc[k] = orders.filter(o => o.status === k).length;
      return acc;
    }, { all: orders.length });
  }, [orders]);

  const confirm = async (id) => {
    setBusy(id);
    try {
      await window.API.adminConfirm(id, '');
      await load();
    } catch (err) {
      alert(`确认失败：${err?.message || err}`);
    } finally {
      setBusy(null);
    }
  };

  const refund = async (id) => {
    if (!confirm_native('确定要标记此订单为已退款？')) return;
    setBusy(id);
    try {
      await window.API.adminRefund(id, '管理员退款');
      await load();
    } catch (err) {
      alert(`退款失败：${err?.message || err}`);
    } finally {
      setBusy(null);
    }
  };

  const reprocess = async (id) => {
    setBusy(id);
    try {
      await window.API.adminReprocess(id);
      await load();
    } catch (err) {
      alert(`重跑失败：${err?.message || err}`);
    } finally {
      setBusy(null);
    }
  };

  return (
    <div className="min-h-screen bg-ink-50">
      <div className="bg-white border-b border-ink-200">
        <div className="max-w-[1280px] mx-auto px-6 lg:px-8 h-14 flex items-center justify-between">
          <div className="flex items-center gap-3">
            <I.Logo size={26} />
            <div className="text-[14px] font-semibold text-navy-900">墨鉴管理后台</div>
            <Badge tone="ink" className="mono">v0.1 · INTERNAL</Badge>
          </div>
          <div className="flex items-center gap-3 text-[12.5px] text-ink-500">
            <a onClick={() => navigate('home')} className="hover:text-navy-900 cursor-pointer">回到主站</a>
            <span className="w-px h-4 bg-ink-200" />
            <a onClick={onLogout} className="hover:text-bad-600 cursor-pointer">注销</a>
          </div>
        </div>
      </div>

      <div className="max-w-[1280px] mx-auto px-6 lg:px-8 py-8">
        {/* 实时看板 */}
        {stats && (
          <div className="grid grid-cols-2 md:grid-cols-5 gap-3 mb-6">
            <StatTile label="今日订单"     value={stats.orders_today} />
            <StatTile label="今日收入" value={`¥ ${stats.revenue_today.toFixed(2)}`} accent="ok" />
            <StatTile label="待确认收款" value={stats.pending_confirm} accent="warn" />
            <StatTile label="今日已完成" value={stats.completed_today} accent="brand" />
            <StatTile label="候补名单"   value={stats.waitlist_total} />
          </div>
        )}

        <div className="flex items-end justify-between flex-wrap gap-4">
          <div>
            <h1 className="text-[24px] font-bold text-navy-900">订单管理</h1>
            <p className="mt-1 text-[13px] text-ink-500">手动确认支付到账 · 触发 LLM 检测 · 监控订单状态。{loading ? ' · 加载中...' : ` · 共 ${total} 单`}</p>
          </div>
          <div className="flex items-center gap-3">
            <div className="relative">
              <I.Search size={14} className="absolute left-3 top-1/2 -translate-y-1/2 text-ink-400" />
              <input value={q} onChange={e => setQ(e.target.value)} placeholder="搜索金额尾数(0-99) / 订单号 / 文件名"
                     className="h-10 pl-9 pr-3 w-[320px] rounded-lg ring-1 ring-ink-200 bg-white text-[13.5px] focus:outline-none focus:ring-2 focus:ring-brand-500" />
            </div>
            <Button kind="secondary" size="md" icon={<I.Refresh size={14} />} onClick={load}>刷新</Button>
          </div>
        </div>

        {errMsg && (
          <div className="mt-4 p-3 rounded-lg bg-bad-50 ring-1 ring-bad-100 text-[12.5px] text-bad-600">
            {errMsg}
          </div>
        )}

        <div className="mt-6 flex flex-wrap items-center gap-2">
          <FilterChip label={`全部`} count={counts.all} active={statusFilter === 'all'} onClick={() => setStatus('all')} />
          {Object.values(ADMIN_STATUSES).map(s => (
            <FilterChip key={s.key} label={s.label} count={counts[s.key] || 0} dot={s.dotClass}
                        active={statusFilter === s.key} onClick={() => setStatus(s.key)} />
          ))}
        </div>

        <Card className="mt-5 overflow-hidden">
          <div className="overflow-x-auto">
            <table className="w-full text-[13px]">
              <thead className="bg-ink-50/80 text-ink-500 text-[11.5px] uppercase tracking-wide">
                <tr className="text-left">
                  <Th className="w-[170px]">订单号</Th>
                  <Th className="w-[160px]">上传时间</Th>
                  <Th>文件名</Th>
                  <Th className="w-[80px] text-right">字数</Th>
                  <Th className="w-[100px] text-right">金额</Th>
                  <Th className="w-[150px]">状态</Th>
                  <Th className="w-[260px] text-right">操作</Th>
                </tr>
              </thead>
              <tbody>
                {orders.map(o => {
                  const isBusy = busyId === o.id;
                  return (
                    <tr key={o.id} className="border-t border-ink-200 hover:bg-ink-50/60">
                      <Td><span className="mono text-[12px] text-navy-900">{o.id}</span></Td>
                      <Td><span className="num text-ink-700 text-[12px]">{new Date(o.created_at).toLocaleString('zh-CN')}</span></Td>
                      <Td><span className="text-ink-700 truncate block max-w-[320px]">{o.file_name}</span></Td>
                      <Td className="text-right num text-ink-700">{o.word_count.toLocaleString()}</Td>
                      <Td className="text-right num text-navy-900 font-semibold">¥ {o.amount.toFixed(2)}</Td>
                      <Td><StatusPill status={o.status} /></Td>
                      <Td className="text-right">
                        <div className="inline-flex items-center gap-1.5">
                          {(o.status === 'pending' || o.status === 'uploaded') && (
                            <Button kind="dark" size="sm" onClick={() => confirm(o.id)} disabled={isBusy}
                                    icon={isBusy ? <I.Spinner size={12} /> : <I.Check size={12} />}>
                              确认收款
                            </Button>
                          )}
                          {(o.status === 'llm_failed' || o.status === 'processing') && (
                            <Button kind="secondary" size="sm" onClick={() => reprocess(o.id)} disabled={isBusy} icon={<I.Refresh size={12} />}>
                              重跑
                            </Button>
                          )}
                          {(o.status === 'done' || o.status === 'processing') && o.report_id && (
                            <Button kind="secondary" size="sm" onClick={() => navigate('report', { id: o.id })} icon={<I.Eye size={12} />}>
                              详情
                            </Button>
                          )}
                          {o.status !== 'refunded' && o.status !== 'expired' && (
                            <button onClick={() => refund(o.id)} disabled={isBusy}
                                    className="text-[12px] text-ink-500 hover:text-bad-600 px-2 h-7 rounded">
                              退款
                            </button>
                          )}
                        </div>
                      </Td>
                    </tr>
                  );
                })}
                {orders.length === 0 && !loading && (
                  <tr><td colSpan="7" className="py-14 text-center text-ink-400 text-[13px]">暂无订单</td></tr>
                )}
                {loading && orders.length === 0 && (
                  <tr><td colSpan="7" className="py-14 text-center text-ink-400 text-[13px]"><I.Spinner size={16} className="inline mr-2" />加载中...</td></tr>
                )}
              </tbody>
            </table>
          </div>
        </Card>

        <div className="mt-5 p-4 rounded-xl bg-white ring-1 ring-ink-200 flex items-start gap-3">
          <I.Info size={16} className="text-brand-600 mt-0.5" />
          <div className="text-[12.5px] text-ink-500 leading-relaxed">
            <strong className="text-navy-900">工作流：</strong> 用户上传论文 → 系统生成订单（待支付）→ 用户扫码支付 → 你手机收到支付宝通知 →
            在此搜索"金额尾数（如 42）"快速定位 → 点击「确认收款」→ 系统自动进入「LLM 处理中」并在 30 秒后切到「已完成」，用户的等待页会自动跳转到报告。
            <br />
            数据每 8 秒自动刷新。
          </div>
        </div>
      </div>
    </div>
  );
}

function StatTile({ label, value, accent = 'ink' }) {
  const accents = {
    ink: 'text-navy-900',
    ok: 'text-ok-600',
    warn: 'text-warn-600',
    brand: 'text-brand-600',
  };
  return (
    <div className="p-4 rounded-xl bg-white ring-1 ring-ink-200">
      <div className="text-[11px] uppercase tracking-wider text-ink-500 font-semibold">{label}</div>
      <div className={`mt-1 num text-[24px] font-bold ${accents[accent]}`}>{value}</div>
    </div>
  );
}

function Th({ children, className = '' }) {
  return <th className={`px-4 py-3 font-medium ${className}`}>{children}</th>;
}
function Td({ children, className = '' }) {
  return <td className={`px-4 py-3 ${className}`}>{children}</td>;
}

function FilterChip({ label, count, dot, active, onClick }) {
  return (
    <button onClick={onClick}
      className={`h-8 px-3 inline-flex items-center gap-2 rounded-full text-[12.5px] transition-all
        ${active ? 'bg-navy-900 text-white' : 'bg-white ring-1 ring-ink-200 text-ink-700 hover:bg-ink-50'}`}>
      {dot && <span className={`w-1.5 h-1.5 rounded-full ${dot}`} />}
      <span>{label}</span>
      <span className={`num text-[11.5px] ${active ? 'text-white/70' : 'text-ink-400'}`}>{count}</span>
    </button>
  );
}

// 浏览器原生 confirm，避免和上面 confirm() 函数重名
function confirm_native(msg) {
  return window.confirm(msg);
}

window.AdminPage = AdminPage;
