/* Robindex v2 — Admin risk console: real read-only risk API.
   - Admin key from sessionStorage(rx2.adminKey); 401 clears it → back to login.
   - Parallel GET /api/admin/risk/disputes?limit=50 + /api/admin/risk/banned?limit=50,
     headers x-admin-key. Loading role=status, error role=alert + retry.
   - Per-row "证据/Evidence" button: on-demand GET /api/admin/risk/disputes/:id/evidence,
     expands ToS / payments / recent ledger count+time below the row.
   - Never fabricates fields. IP masked to first two octets; UA never shown.
   - No mock fallback. Existing classes reused; new copy bilingual en/zh. */
const { useState: adS, useEffect: adE } = React;

function AdminPage({ lang }) {
  const { Icon } = window.RXC;
  const E = window.RXE;
  const SK = "rx2.adminKey";
  const L = (en, zh) => (lang === "zh" ? zh : en);
  const zh = lang === "zh";

  const [adminKey, setAdminKey] = adS(() => {
    try { return sessionStorage.getItem(SK) || ""; } catch (_) { return ""; }
  });
  const [pwd, setPwd] = adS("");
  const [disputes, setDisputes] = adS([]);
  const [banned, setBanned] = adS([]);
  const [loading, setLoading] = adS(false);
  const [err, setErr] = adS(null);
  const [tick, setTick] = adS(0);
  const [expanded, setExpanded] = adS({});       // { [disputeId]: bool }
  const [evCache, setEvCache] = adS({});          // { [disputeId]: { loading, err, data } }

  const clearKey = () => {
    try { sessionStorage.removeItem(SK); } catch (_) {}
    setAdminKey("");
    setDisputes([]); setBanned([]); setExpanded({}); setEvCache({});
  };
  const connect = () => {
    const k = pwd.trim();
    if (!k) return;
    try { sessionStorage.setItem(SK, k); } catch (_) {}
    setAdminKey(k);
    setPwd("");
    setErr(null);
  };

  adE(() => {
    if (!adminKey) return;
    let cancelled = false;
    (async () => {
      setLoading(true); setErr(null);
      const headers = { "x-admin-key": adminKey };
      const get = (url) => fetch(url, { headers }).then((r) => r.json().then((b) => ({ status: r.status, body: b })));
      try {
        const [dr, br] = await Promise.all([
          get("/api/admin/risk/disputes?limit=50"),
          get("/api/admin/risk/banned?limit=50"),
        ]);
        if (cancelled) return;
        const unauth = dr.status === 401 || br.status === 401
          || (dr.body && dr.body.error === "unauthorized")
          || (br.body && br.body.error === "unauthorized");
        if (unauth) { clearKey(); return; }
        if (dr.status >= 400 || br.status >= 400) { setErr("server_error"); return; }
        setDisputes((dr.body && dr.body.items) || []);
        setBanned((br.body && br.body.items) || []);
      } catch (_) {
        if (!cancelled) setErr("network_error");
      } finally {
        if (!cancelled) setLoading(false);
      }
    })();
    return () => { cancelled = true; };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [adminKey, tick]);

  const fetchEvidence = async (id) => {
    const cached = evCache[id];
    if (cached && cached.loading) return;
    if (cached && cached.data) { setExpanded((m) => ({ ...m, [id]: !m[id] })); return; }
    setExpanded((m) => ({ ...m, [id]: true }));
    setEvCache((m) => ({ ...m, [id]: { loading: true } }));
    try {
      const r = await fetch(`/api/admin/risk/disputes/${encodeURIComponent(id)}/evidence`, { headers: { "x-admin-key": adminKey } });
      if (r.status === 401) { clearKey(); return; }
      const b = await r.json();
      if (r.status >= 400) { setEvCache((m) => ({ ...m, [id]: { err: (b && b.error) || "server_error" } })); return; }
      setEvCache((m) => ({ ...m, [id]: { data: b } }));
    } catch (_) {
      setEvCache((m) => ({ ...m, [id]: { err: "network_error" } }));
    }
  };

  // ---- login screen ----
  if (!adminKey) {
    return (
      <div className="v2-page" data-screen-label="admin">
        <div className="v2-wrap narrow">
          <div className="v2-head">
            <h1>{T2("adTitle")}</h1>
            <p>{T2("adSub")}</p>
          </div>
          <div className="v2-card" style={{ padding: 18, display: "flex", flexDirection: "column", gap: 10 }}>
            <label style={{ font: "600 11px var(--mono)", letterSpacing: ".1em", textTransform: "uppercase", color: "var(--faint)" }}>{L("Admin key", "管理员密钥")}</label>
            <input type="password" value={pwd} onChange={(e) => setPwd(e.target.value)} onKeyDown={(e) => { if (e.key === "Enter") connect(); }}
              placeholder={L("Enter admin key", "输入管理员密钥")} autoFocus
              style={{ padding: "10px 12px", borderRadius: "var(--r)", border: "1px solid var(--border)", background: "var(--panel-2)", color: "var(--text)", font: "500 14px var(--mono)" }} />
            <button className="x2-primary" disabled={!pwd.trim()} onClick={connect}><Icon name="shield" size={14} />{L("Connect", "连接")}</button>
          </div>
        </div>
      </div>
    );
  }

  // ---- derived metrics (only from returned data) ----
  const openCount = disputes.filter((d) => (d.dispute && d.dispute.status) === "open").length;
  const stats = [
    { k: T2("adDisputes"), v: disputes.length, s: L(`${openCount} open`, `${openCount} 进行中`), icon: "shield" },
    { k: L("Open", "进行中"), v: openCount, s: L("in evidence review", "证据审核中"), icon: "clock" },
    { k: T2("adBans"), v: banned.length, s: L("banned accounts", "已封禁账户"), icon: "lock" },
  ];

  const loadingText = zh ? "加载中…" : "Loading…";
  const errText = err === "network_error"
    ? (zh ? "网络错误，请重试" : "Network error, please retry")
    : (zh ? "加载失败，请重试" : "Failed to load, please retry");
  const retryLabel = zh ? "重试" : "Retry";
  const disconnectLabel = zh ? "断开" : "Disconnect";
  const evidenceLabel = T2("adEvidence");
  const noDataLabel = zh ? "暂无数据" : "No data";

  const stFor = (d) => {
    const st = (d.dispute && d.dispute.status) || "open";
    if (st === "won") return <span className="ad-st won"><Icon name="check" size={10} />{T2("adStWon")}</span>;
    if (st === "lost") return <span className="ad-st ban"><Icon name="lock" size={10} />{T2("adStBan")}</span>;
    return <span className="ad-st rev"><Icon name="clock" size={10} />{T2("adStEvidence")}</span>;
  };
  const maskIp = (ip) => {
    if (!ip) return null;
    const parts = String(ip).split(".");
    if (parts.length !== 4) return "x.x";
    return parts[0] + "." + parts[1] + ".x.x";
  };
  const fmtCents = (c, cur) => (c == null ? "—" : (cur || "USD") + " " + (Number(c) / 100).toFixed(2));

  return (
    <div className="v2-page" data-screen-label="admin">
      <div className="v2-wrap">
        <div className="v2-head">
          <h1>{T2("adTitle")}</h1>
          <p>{T2("adSub")}</p>
          <button className="btn-ghost" style={{ marginTop: 10 }} onClick={clearKey}><Icon name="x" size={12} />{disconnectLabel}</button>
        </div>
        {err ? (
          <div className="v2-card" style={{ padding: 18 }}>
            <div className="x2-note x2-danger" role="alert"><Icon name="shield" size={13} style={{ flex: "none", marginTop: 1 }} />{errText}</div>
            <button className="btn-ghost" style={{ marginTop: 10 }} onClick={() => setTick((t) => t + 1)}><Icon name="refresh" size={12} />{retryLabel}</button>
          </div>
        ) : loading ? (
          <div className="v2-card" style={{ padding: 18, textAlign: "center", color: "var(--dim)" }} role="status">{loadingText}</div>
        ) : (
          <React.Fragment>
            <div className="ad-grid">
              {stats.map((s) => (
                <div className="v2-card w-stat" key={s.k}>
                  <div className="k"><Icon name={s.icon} size={12} />{s.k}</div>
                  <div className="v">{s.v}</div>
                  <div className="s">{s.s}</div>
                </div>
              ))}
            </div>

            <div className="v2-sec"><Icon name="shield" size={12} />{T2("adTable")}</div>
            <div className="v2-card" style={{ padding: "4px 10px", overflowX: "auto" }}>
              <table className="ad-table">
                <thead>
                  <tr><th>ID</th><th>{T2("adUser")}</th><th>{T2("adAmt")}</th><th>{T2("adReason")}</th><th>{T2("adStatus")}</th><th>{T2("adAction")}</th></tr>
                </thead>
                <tbody>
                  {disputes.length === 0 && (
                    <tr><td colSpan={6} style={{ textAlign: "center", color: "var(--faint)", padding: "20px" }}>{noDataLabel}</td></tr>
                  )}
                  {disputes.map((d) => {
                    const dis = d.dispute || {};
                    const u = d.user || {};
                    const id = dis.id;
                    const ex = expanded[id];
                    const ev = evCache[id] || {};
                    return (
                      <React.Fragment key={id}>
                        <tr>
                          <td><span className="v2-mono" style={{ color: "var(--faint)" }}>{id}</span><div className="lg-ts">{dis.opened_at ? E.fmtDT(dis.opened_at).slice(5) : "—"}</div></td>
                          <td>
                            <b>{dis.user_id}</b>
                            {u.flag && <div className="lg-s" style={{ color: "var(--down)" }}>flag: {u.flag}</div>}
                            {u.banned_at != null && <div className="lg-s" style={{ color: "var(--down)" }}>{T2("adStBan")}</div>}
                          </td>
                          <td><b className="v2-mono">{dis.amount == null ? "—" : E.usd(dis.amount)}</b><div className="lg-s">{dis.provider}</div></td>
                          <td>{dis.reason || "—"}</td>
                          <td>{stFor(d)}</td>
                          <td>
                            <button className="btn-ghost" style={{ padding: "4px 9px", font: "500 11px var(--mono)" }} onClick={() => fetchEvidence(id)}>
                              <Icon name="quote" size={11} />{evidenceLabel}{ex ? " ▲" : " ▼"}
                            </button>
                          </td>
                        </tr>
                        {ex && (
                          <tr>
                            <td colSpan={6} style={{ background: "var(--panel-2)", padding: "12px 14px", borderBottom: "1px solid var(--border-soft)" }}>
                              {ev.loading ? (
                                <div role="status" style={{ color: "var(--dim)", font: "400 12px var(--sans)" }}>{loadingText}</div>
                              ) : ev.err ? (
                                <div role="alert" className="x2-note x2-danger" style={{ margin: 0 }}><Icon name="shield" size={13} style={{ flex: "none", marginTop: 1 }} />{errText}</div>
                              ) : ev.data ? (
                                <AdminEvidenceView data={ev.data} lang={lang} maskIp={maskIp} fmtCents={fmtCents} />
                              ) : null}
                            </td>
                          </tr>
                        )}
                      </React.Fragment>
                    );
                  })}
                </tbody>
              </table>
            </div>

            <div className="v2-sec"><Icon name="lock" size={12} />{L("Banned accounts", "封禁账户")}</div>
            <div className="v2-card" style={{ padding: "4px 10px", overflowX: "auto" }}>
              <table className="ad-table">
                <thead>
                  <tr><th>{T2("adUser")}</th><th>{L("Flag", "标记")}</th><th>{L("Banned at", "封禁时间")}</th><th>{L("Cash", "现金余额")}</th><th>{L("Reward", "赠点")}</th><th>{L("Owner", "本人余额")}</th></tr>
                </thead>
                <tbody>
                  {banned.length === 0 && (
                    <tr><td colSpan={6} style={{ textAlign: "center", color: "var(--faint)", padding: "20px" }}>{noDataLabel}</td></tr>
                  )}
                  {banned.map((b) => (
                    <tr key={b.user_id}>
                      <td><b>{b.user_id}</b></td>
                      <td>{b.flag || "—"}</td>
                      <td><span className="lg-ts">{b.banned_at ? E.fmtDT(b.banned_at) : "—"}</span></td>
                      <td><b className="v2-mono">{E.usd(b.cash_balance)}</b></td>
                      <td><b className="v2-mono">{E.usd(b.reward_balance)}</b></td>
                      <td><b className="v2-mono">{E.usd(b.owner_balance)}</b></td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>

            <div className="v2-sec"><Icon name="shield" size={12} />{T2("adPolicy")}</div>
            <div className="v2-card ad-policy">
              {[T2("adP1"), T2("adP2"), T2("adP3")].map((p, i) => (
                <div className="li" key={i}><i></i><span>{p}</span></div>
              ))}
            </div>
          </React.Fragment>
        )}
      </div>
    </div>
  );
}

/* Per-dispute evidence expansion: ToS acceptances + payments + recent ledger
   count/time. IP masked to first two octets; UA never rendered (API drops it). */
function AdminEvidenceView({ data, lang, maskIp, fmtCents }) {
  const E = window.RXE;
  const L = (en, zh) => (lang === "zh" ? zh : en);
  const tos = data.tos_acceptances || [];
  const pays = data.payments || [];
  const led = data.ledger_recent || [];
  const ledgerCount = led.length;
  const ledgerEarliest = ledgerCount ? led[ledgerCount - 1].ts : null;
  const ledgerLatest = ledgerCount ? led[0].ts : null;
  const head = { font: "600 10.5px var(--mono)", letterSpacing: ".09em", textTransform: "uppercase", color: "var(--faint)", marginBottom: 4 };
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 10, font: "400 12px var(--sans)", color: "var(--dim)" }}>
      <div>
        <div style={head}>{L("ToS acceptances", "协议同意记录")}</div>
        {tos.length === 0 ? <div style={{ color: "var(--faint)" }}>—</div> : (
          <ul className="ad-ev" style={{ margin: 0 }}>
            {tos.map((t, i) => (
              <li key={i}>{E.fmtDT(t.ts)} · {t.kind}{t.ip ? " · IP " + maskIp(t.ip) : ""}{t.ref ? " · " + t.ref : ""}</li>
            ))}
          </ul>
        )}
      </div>
      <div>
        <div style={head}>{L("Payments", "支付记录")}</div>
        {pays.length === 0 ? <div style={{ color: "var(--faint)" }}>—</div> : (
          <ul className="ad-ev" style={{ margin: 0 }}>
            {pays.map((p, i) => (
              <li key={i}>{p.created_at ? E.fmtDT(p.created_at) : "—"} · {p.provider} · {p.kind || "—"} · {fmtCents(p.amount_cents, p.currency)} · {p.status || "—"}</li>
            ))}
          </ul>
        )}
      </div>
      <div>
        <div style={head}>{L("Recent ledger", "最近流水")}</div>
        {ledgerCount === 0 ? <div style={{ color: "var(--faint)" }}>—</div> : (
          <div style={{ font: "400 11.5px var(--mono)", color: "var(--dim)" }}>
            {L(`${ledgerCount} entries`, `${ledgerCount} 条`)} · {L("latest", "最新")} {E.fmtDT(ledgerLatest)} · {L("earliest", "最早")} {E.fmtDT(ledgerEarliest)}
          </div>
        )}
      </div>
    </div>
  );
}
Object.assign(window, { AdminPage });
