// Users page — list + detail drawer
// Matches spec: list filters by role/status, fields incl. join date & total spending;
// detail page with KYC, account status, orders & disputes; actions: warn / temp ban / perm ban / unban / force logout

const USER_STATUS = {
  active: { label: "正常", tone: "success" },
  warning: { label: "警告", tone: "warn" },
  suspended: { label: "封鎖中", tone: "danger" },
  pending: { label: "待審核", tone: "warn" },
};

// Assume current admin is A001 (super_admin) — wired through so temp-ban / perm-ban can gate
const CURRENT_ROLE = "super_admin";

const UsersPage = () => {
  const [tab, setTab] = useState("all");
  const [query, setQuery] = useState("");
  const [role, setRole] = useState("all");
  const [status, setStatus] = useState("all");
  const [selected, setSelected] = useState(new Set());
  const [detailUser, setDetailUser] = useState(null);
  // action dialogs
  const [flaggedUserIds, setFlaggedUserIds] = useState(new Set());
  const [page, setPage] = useState(0);
  const [msgUser, setMsgUser] = useState(null);
  const [tempBanUser, setTempBanUser] = useState(null);
  const [permBanUser, setPermBanUser] = useState(null);
  const [unbanUser, setUnbanUser] = useState(null);
  const [logoutUser, setLogoutUser] = useState(null);
  // violation flow state
  const [addPointUser, setAddPointUser] = useState(null);
  const [lockUser, setLockUser] = useState(null);
  const [violationEdits, setViolationEdits] = useState({}); // userId -> override data
  const toast = useToast();

  const [users, setUsers] = useState(MOCK.USERS);
  const [usersLoading, setUsersLoading] = useState(false);
  const loadUsers = () => {
    setUsersLoading(true);
    fetch("/api/admin/users")
      .then(r => r.ok ? r.json() : null)
      .then(data => { if (Array.isArray(data) && data.length > 0) setUsers(data); })
      .catch(() => {})
      .finally(() => setUsersLoading(false));
  };
  useEffect(() => { loadUsers(); }, []);

  // Augment violations with local overrides; prefer real DB data over mock
  const getLiveViolation = (user) => {
    const base = user.violationPoints !== undefined
      ? { points: user.violationPoints, entries: user.violationEntries ?? [], locks: null }
      : getViolationData(user);
    const ov = violationEdits[user.id];
    if (!ov) return base;
    return {
      points: ov.points ?? base.points,
      entries: ov.entries ?? base.entries,
      locks: ov.locks !== undefined ? ov.locks : base.locks,
    };
  };

  const filtered = users
    .filter(u => {
      if (tab === "artist" && u.role !== "illustrator" && u.role !== "author") return false;
      if (tab === "client" && u.role !== "commissioner") return false;
      if (tab === "pending" && u.status !== "pending") return false;
      if (tab === "flagged" && u.status !== "warning" && !flaggedUserIds.has(u.id)) return false;
      if (tab === "threshold" && !(u.status === "suspended" || getLiveViolation(u).points >= 3)) return false;
      if (role === "creator" && u.role !== "illustrator" && u.role !== "author") return false;
      else if (role !== "all" && role !== "creator" && u.role !== role) return false;
      if (status !== "all" && u.status !== status) return false;
      if (query) {
        const q = query.toLowerCase();
        if (!u.name.toLowerCase().includes(q) && !u.id.toLowerCase().includes(q) && !u.email.toLowerCase().includes(q)) return false;
      }
      return true;
    })
    .sort((a, b) => (flaggedUserIds.has(b.id) ? 1 : 0) - (flaggedUserIds.has(a.id) ? 1 : 0));

  useEffect(() => { setPage(0); }, [tab, query, role, status]);

  const handleReveal = (type, userId, cb) => {
    cb();
    toast({ title: "已記錄存取紀錄", message: `查看 ${userId} 的${type === "phone" ? "電話" : type === "bank" ? "銀行帳號" : "Email"} · 已寫入審計日誌`, icon: "scroll" });
  };

  const toggleFlagUser = (userId) => {
    setFlaggedUserIds(prev => {
      const next = new Set(prev);
      if (next.has(userId)) next.delete(userId); else next.add(userId);
      return next;
    });
  };

  const openAction = (action, user) => {
    setDetailUser(null);
    if (action === "flag") { toggleFlagUser(user.id); return; }
    else if (action === "msg") setMsgUser(user);
    else if (action === "tempBan") setTempBanUser(user);
    else if (action === "permBan") setPermBanUser(user);
    else if (action === "unban") setUnbanUser(user);
    else if (action === "logout") setLogoutUser(user);
    else if (action === "addPoint") setAddPointUser(user);
    else if (action === "lock") setLockUser(user);
    else if (action === "unlock") {
      setViolationEdits(prev => {
        const cur = getLiveViolation(user);
        return { ...prev, [user.id]: { points: cur.points, entries: cur.entries, locks: null } };
      });
      toast({ title: "已解除所有功能鎖定", message: `${user.name} 可恢復全部功能使用` });
    }
    else if (action === "dismissPoint") {
      const { user: u, entry, currentViolation } = user;
      const filtered = currentViolation.entries.filter(e => e.id !== entry.id);
      const pointsToRemove = entry.points || entry.delta || 1;
      const newPoints = Math.max(0, currentViolation.points - pointsToRemove);
      setViolationEdits(prev => ({
        ...prev,
        [u.id]: { points: newPoints, entries: filtered, locks: currentViolation.locks },
      }));
      fetch(`/api/admin/users/${u.id}/violation`, {
        method: "PATCH",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ points: newPoints, entries: filtered, dismissedEntry: entry }),
      }).then(r => r.json()).then(d => console.log("[dismissPoint PATCH]", d)).catch(e => console.error("[dismissPoint PATCH error]", e));
      logAudit("撤銷違規點數", u, { entryId: entry.id, pointsRemoved: pointsToRemove, reason: entry.reason || "" });
      toast({ title: "違規已撤銷", message: `${u.name} · 點數已扣回 ${pointsToRemove} 點` });
    }
  };

  // Count how many users are at threshold
  const atThresholdCount = users.filter(u => getLiveViolation(u).points >= 3 && !getLiveViolation(u).locks).length;

  return (
    <div className="fade-in">
      <PageHeader
        title="用戶管理"
        subtitle={`${users.filter(u=>u.role==="illustrator"||u.role==="author").length} 位創作者 · ${users.filter(u=>u.role==="commissioner").length} 位委託人`}
        actions={<>
          <Button variant="secondary" icon="refresh" disabled={usersLoading} onClick={loadUsers}>重新整理</Button>
          <Button variant="secondary" icon="download" onClick={() => {
            csvDownload(`users_${Date.now()}.csv`,
              ["ID","名稱","Email","角色","狀態","加入日期"],
              filtered.map(u => [u.id, u.name, u.email, u.level || u.role, u.status, u.joinedAt])
            );
          }}>匯出 CSV</Button>
        </>}
      />

      {atThresholdCount > 0 && (
        <div style={{
          display: "flex", alignItems: "center", gap: 12,
          padding: "12px 16px", background: "var(--danger-soft)",
          border: "1px solid var(--danger)", borderRadius: 10,
          marginBottom: 16,
        }}>
          <div style={{
            width: 32, height: 32, borderRadius: 8,
            background: "var(--danger)", color: "#fff",
            display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0,
          }}><Icon name="alert" size={16}/></div>
          <div style={{ flex: 1, fontSize: 13 }}>
            <b style={{ color: "var(--danger)" }}>{atThresholdCount} 位用戶累計違規 3 點尚未處理</b>
            <span style={{ marginLeft: 8, color: "var(--ink-2)" }}>· 請儘速裁定鎖定範圍或封鎖帳號</span>
          </div>
          <Button size="sm" variant="secondary" onClick={() => setTab("threshold")}>只看這些用戶</Button>
        </div>
      )}

      <div style={{ marginBottom: 16 }}>
        <Tabs
          active={tab} onChange={setTab}
          tabs={[
            { value: "all", label: "全部", count: users.length },
            { value: "artist", label: "創作者", count: users.filter(u=>u.role==="illustrator"||u.role==="author").length },
            { value: "client", label: "委託人", count: users.filter(u=>u.role==="commissioner").length },
            { value: "pending", label: "待審核", count: users.filter(u=>u.status==="pending").length },
            { value: "flagged", label: "已標記", count: users.filter(u=>u.status==="warning" || flaggedUserIds.has(u.id)).length },
            { value: "threshold", label: "停權中", count: users.filter(u=>u.status==="suspended" || getLiveViolation(u).points >= 3).length },
          ]}
        />
      </div>

      {/* Filter bar */}
      <div style={{ display: "flex", gap: 10, alignItems: "center", marginBottom: 14, flexWrap: "wrap" }}>
        <div style={{ flex: 1, maxWidth: 360, minWidth: 260 }}>
          <Input icon="search" placeholder="搜尋姓名、UID、Email…" value={query} onChange={e => setQuery(e.target.value)}/>
        </div>
        <Select value={role} onChange={setRole} icon="filter" options={[
          { value: "all", label: "所有角色" },
          { value: "creator", label: "創作者" },
          { value: "illustrator", label: "創作者 · 繪師" },
          { value: "author", label: "創作者 · 作者" },
          { value: "commissioner", label: "委託人" },
        ]}/>
        <Select value={status} onChange={setStatus} options={[
          { value: "all", label: "所有狀態" },
          { value: "active", label: "正常" },
          { value: "warning", label: "警告中" },
          { value: "suspended", label: "封鎖中" },
          { value: "pending", label: "待審核" },
        ]}/>
        <div style={{ flex: 1 }}/>
        <div style={{ fontSize: 12, color: "var(--ink-3)" }}>{filtered.length} 位用戶</div>
      </div>

      {/* Bulk bar */}
      {selected.size > 0 && (
        <div style={{
          display: "flex", alignItems: "center", gap: 12,
          padding: "10px 16px", background: "var(--ink)", color: "#fff",
          borderRadius: 10, marginBottom: 12,
        }}>
          <span style={{ fontSize: 13 }}>已選取 <b>{selected.size}</b> 位</span>
          <div style={{ flex: 1 }}/>
          <button style={{ fontSize: 13, color: "#fff", opacity: 0.85, padding: "6px 10px" }}>發送站內信</button>
          <button style={{ fontSize: 13, color: "#fff", opacity: 0.85, padding: "6px 10px" }}>匯出選取</button>
          <button style={{ fontSize: 13, color: "var(--warn)", padding: "6px 10px" }} onClick={() => { setFlaggedUserIds(prev => { const next = new Set(prev); selected.forEach(id => next.add(id)); return next; }); setSelected(new Set()); }}>批次標記</button>
          <button onClick={() => setSelected(new Set())} style={{ color: "#fff", opacity: 0.6, padding: 4 }}><Icon name="x" size={14}/></button>
        </div>
      )}

      <Table
        selectable
        selected={selected}
        onSelect={setSelected}
        onRowClick={u => setDetailUser(u)}
        columns={[
          { title: "用戶", render: u => (
            <div style={{ display: "flex", alignItems: "center", gap: 6 }}>
              {flaggedUserIds.has(u.id) && <span style={{ color: "var(--warn)", fontSize: 14, lineHeight: 1 }}>★</span>}
              <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
                {u.avatar.url
                  ? <img src={u.avatar.url} style={{ width: 32, height: 32, borderRadius: "50%", objectFit: "cover", flexShrink: 0 }}/>
                  : <Avatar hue={u.avatar.hue} glyph={u.avatar.glyph} size={32}/>
                }
                <div style={{ minWidth: 0 }}>
                  <div style={{ fontSize: 13.5, fontWeight: 500, display: "flex", alignItems: "center", gap: 6 }}>
                    {u.name}
                    {u.kycVerified && <Icon name="shield" size={12} style={{ color: "var(--success)" }} title="成年已驗證"/>}
                  </div>
                  <div className="mono" style={{ fontSize: 11.5, color: "var(--ink-3)" }}>{u.uid ?? "—"}</div>
                </div>
              </div>
            </div>
          ) },
          { title: "角色", render: u => (
            u.role === "illustrator" || u.role === "author"
              ? <Badge tone="accent" size="sm">創作者 · {u.level}</Badge>
              : <Badge tone="info" size="sm">委託人</Badge>
          ) },
          { title: "加入日期", render: u => (
            <div style={{ fontSize: 12.5 }}>
              <div className="mono" style={{ color: "var(--ink-2)" }}>{u.joinedAt}</div>
              <div style={{ color: "var(--ink-4)", fontSize: 11 }}>{relativeJoinLabel(u.joinedAt)}</div>
            </div>
          ) },
          { title: "總金額", align: "right", render: u => (
            <span className="mono" style={{ color: "var(--ink-2)", fontSize: 13 }}>
              {fmtCurrency((u.role === "illustrator" || u.role === "author") ? u.revenue : (u.spent || 0))}
            </span>
          ) },
          { title: "訂單數", align: "right", render: u => <span className="mono" style={{ fontSize: 13 }}>{u.orders}</span> },
          { title: "違規", render: u => {
            const v = getLiveViolation(u);
            if (v.locks) return <Badge tone="warn" size="sm" dot>鎖定中</Badge>;
            if (v.points === 0) return <span style={{ fontSize: 12, color: "var(--ink-4)" }}>—</span>;
            const tone = v.points >= 3 ? "danger" : v.points >= 2 ? "warn" : "default";
            return (
              <div style={{ display: "flex", alignItems: "center", gap: 6 }}>
                <Badge tone={tone} size="sm">{v.points}/3 點</Badge>
                {v.points >= 3 && <Icon name="alert" size={12} style={{ color: "var(--danger)" }}/>}
              </div>
            );
          } },
          { title: "狀態", render: u => <StatusBadge status={u.status}/> },
          { title: "", width: 40, render: u => (
            <button onClick={e => { e.stopPropagation(); }} style={{ padding: 4, color: "var(--ink-3)" }}>
              <Icon name="more" size={16}/>
            </button>
          ) },
        ]}
        rows={filtered.slice(page * 14, (page + 1) * 14)}
      />

      <Pagination total={filtered.length} pageSize={14} page={page} onPageChange={setPage}/>

      <UserDetailDrawer
        user={detailUser}
        violation={detailUser ? getLiveViolation(detailUser) : null}
        onClose={() => setDetailUser(null)}
        onAction={openAction}
        onReveal={handleReveal}
        flaggedUserIds={flaggedUserIds}
      />

      {/* === ACTION DIALOGS === */}
      <ConfirmDialog
        open={!!msgUser} onClose={() => setMsgUser(null)}
        onConfirm={async ({ reason }) => {
          await fetch(`/api/admin/users/${msgUser.id}/notify`, {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify({ type: "admin_message", content: reason }),
          });
          toast({ title: "站內信已送出", message: `${msgUser.name} 已收到你的訊息`, icon: "mail" });
          setMsgUser(null);
        }}
        title={`發送站內信 · ${msgUser?.name || ""}`}
        description="用戶將在通知中心收到這則訊息。"
        variant="info"
        icon="mail"
        confirmText="送出"
        requireReason
        reasonLabel="訊息內容"
        reasonPlaceholder="輸入要傳送給用戶的內容…"
      />

      <ConfirmDialog
        open={!!tempBanUser} onClose={() => setTempBanUser(null)}
        onConfirm={({ reason, extraValue } = {}) => {
          const dur = extraValue || "7d";
          const durLabel = { "3d": "3 天", "7d": "7 天", "14d": "14 天", "30d": "30 天" }[dur] || dur;
          fetch(`/api/admin/users/${tempBanUser.id}/ban`, {
            method: "POST", headers: { "Content-Type": "application/json" },
            body: JSON.stringify({ action: "temp", duration: dur, reason }),
          }).then(r => r.json()).then(data => {
            if (data.ok) {
              const patch = { status: "suspended", bannedUntil: data.bannedUntil, bannedReason: reason };
              setUsers(prev => prev.map(u => u.id === tempBanUser.id ? { ...u, ...patch } : u));
              setDetailUser(prev => prev?.id === tempBanUser.id ? { ...prev, ...patch } : prev);
            }
          }).catch(() => {});
          logAudit("暫時封鎖", tempBanUser, { reason, duration: dur });
          toast({ title: "已暫時封鎖", message: `${tempBanUser.name} 已暫時封鎖 ${durLabel}` });
          setTempBanUser(null);
        }}
        title={`暫時封鎖 · ${tempBanUser?.name || ""}`}
        description="暫時封鎖期間用戶無法登入、下訂單或發布內容。進行中的訂單會轉入糾紛處理流程。封鎖期滿自動解除。"
        variant="warn"
        icon="ban"
        confirmText="確認封鎖"
        requireReason
        reasonLabel="封鎖原因"
        reasonPlaceholder="例:連續 2 次逾期交稿且未回應客服"
        extraField={{ label: "封鎖期限", type: "select", options: [
          { value: "3d", label: "3 天" },
          { value: "7d", label: "7 天" },
          { value: "14d", label: "14 天" },
          { value: "30d", label: "30 天" },
        ], defaultValue: "7d" }}
      />

      <ConfirmDialog
        open={!!permBanUser} onClose={() => setPermBanUser(null)}
        onConfirm={({ reason } = {}) => {
          fetch(`/api/admin/users/${permBanUser.id}/ban`, {
            method: "POST", headers: { "Content-Type": "application/json" },
            body: JSON.stringify({ action: "permanent", reason }),
          }).then(r => r.json()).then(data => {
            if (data.ok) {
              const patch = { status: "suspended", bannedUntil: null, bannedReason: reason };
              setUsers(prev => prev.map(u => u.id === permBanUser.id ? { ...u, ...patch } : u));
              setDetailUser(prev => prev?.id === permBanUser.id ? { ...prev, ...patch } : prev);
            }
          }).catch(() => {});
          logAudit("永久封鎖", permBanUser, { reason });
          toast({ title: "用戶已永久封鎖", message: `${permBanUser.name} · 此操作無法還原，已寫入審計日誌`, tone: "danger" });
          setPermBanUser(null);
        }}
        title={<span><Icon name="shield" size={14} style={{ color: "var(--danger)", marginRight: 6 }}/>永久封鎖 · {permBanUser?.name || ""}</span>}
        description={<>此操作將<b>永久封鎖</b>該用戶,包含作品下架、訂單強制轉糾紛、帳號 ID 列入黑名單。<br/><span style={{ color: "var(--danger)" }}>此操作無法還原,且僅限 Super Admin 執行。</span></>}
        variant="danger"
        icon="shield"
        confirmText="永久封鎖"
        requireReason
        reasonLabel="封鎖原因 (必填 · 將永久記錄)"
        reasonPlaceholder="例:涉嫌詐欺多名業主,已有 3 起警方立案"
        requireText={permBanUser?.id}
        requireTextHint={`請輸入用戶 ID 確認:${permBanUser?.id || ""}`}
      />

      <ConfirmDialog
        open={!!unbanUser} onClose={() => setUnbanUser(null)}
        onConfirm={({ reason } = {}) => {
          fetch(`/api/admin/users/${unbanUser.id}/ban`, {
            method: "POST", headers: { "Content-Type": "application/json" },
            body: JSON.stringify({ action: "unban", reason }),
          }).then(r => r.json()).then(data => {
            if (data.ok) {
              const patch = { status: "active", bannedUntil: null, bannedReason: null };
              setUsers(prev => prev.map(u => u.id === unbanUser.id ? { ...u, ...patch } : u));
              setDetailUser(prev => prev?.id === unbanUser.id ? { ...prev, ...patch } : prev);
            }
          }).catch(() => {});
          logAudit("解除封鎖", unbanUser, { reason });
          toast({ title: "已解除封鎖", message: `${unbanUser.name} 已恢復正常狀態` });
          setUnbanUser(null);
        }}
        title={`解除封鎖 · ${unbanUser?.name || ""}`}
        description="解除封鎖後用戶將立即恢復所有權限,能再次登入、下單與發布作品。違規紀錄仍會保留。"
        variant="info"
        icon="shield"
        confirmText="解除封鎖"
        requireReason
        reasonLabel="解除原因"
        reasonPlaceholder="例:用戶已完成客訴處理與教育訓練"
      />

      <ConfirmDialog
        open={!!logoutUser} onClose={() => setLogoutUser(null)}
        onConfirm={() => {
          logAudit("強制登出", logoutUser);
          toast({ title: "已強制登出", message: `${logoutUser.name} 所有裝置的 Session 已撤銷` });
          setLogoutUser(null);
        }}
        title={`強制登出 · ${logoutUser?.name || ""}`}
        description="用戶所有裝置的 Session 將立即失效,下次操作需重新登入並通過 OTP。帳號狀態不受影響。"
        variant="warn"
        icon="logout"
        confirmText="強制登出"
      />

      {addPointUser && (
        <AddViolationDialog
          user={addPointUser}
          currentPoints={getLiveViolation(addPointUser).points}
          onClose={() => setAddPointUser(null)}
          onConfirm={({ category, points: delta, reason, relatedOrder }) => {
            const cur = getLiveViolation(addPointUser);
            let adminEmail = "unknown";
            try { adminEmail = JSON.parse(localStorage.getItem("duidui_admin_state") || "{}").adminEmail || "unknown"; } catch {}
            const newEntry = {
              id: `V-${Date.now()}`,
              category,
              points: delta,
              reason,
              relatedOrder: relatedOrder || null,
              issuedBy: adminEmail,
              issuedAt: new Date().toLocaleString("zh-TW"),
              dismissed: false,
            };
            const newPoints = Math.min(cur.points + delta, 3);
            const newEntries = [newEntry, ...cur.entries];
            // Optimistic UI update
            setViolationEdits(prev => ({
              ...prev,
              [addPointUser.id]: { points: newPoints, entries: newEntries, locks: cur.locks },
            }));
            // Persist to server (server computes violationPoints from entries)
            fetch(`/api/admin/users/${addPointUser.id}/violation`, {
              method: "POST",
              headers: { "Content-Type": "application/json" },
              body: JSON.stringify({ entry: newEntry }),
            }).catch(() => {});
            logAudit("累計違規點數", addPointUser, { category, points: delta, reason, relatedOrder, newPoints });
            toast({
              title: `已累計 ${delta} 點違規`,
              message: newPoints >= 3
                ? `${addPointUser.name} 已達處置門檻，請裁定鎖定範圍`
                : `${addPointUser.name} 目前 ${newPoints}/3 點`,
              tone: newPoints >= 3 ? "danger" : "warn",
            });
            setAddPointUser(null);
          }}
        />
      )}

      {lockUser && (
        <LockFeaturesDialog
          user={lockUser}
          existing={getLiveViolation(lockUser).locks}
          onClose={() => setLockUser(null)}
          onConfirm={({ features, duration, reason }) => {
            const cur = getLiveViolation(lockUser);
            const durLabels = { "7d": "7 天後自動解除", "14d": "14 天後自動解除", "30d": "30 天後自動解除", "permanent": "永久 · 需人工解除" };
            setViolationEdits(prev => ({
              ...prev,
              [lockUser.id]: {
                points: cur.points,
                entries: cur.entries,
                locks: {
                  features,
                  lockedBy: "林佩芸",
                  lockedAt: "剛剛",
                  expiresAt: durLabels[duration] || duration,
                  reason,
                },
              }
            }));
            logAudit(cur.locks ? "更新功能鎖定" : "鎖定功能", lockUser, { features, duration, reason });
            toast({
              title: cur.locks ? "已更新鎖定範圍" : "功能已鎖定",
              message: `${lockUser.name} · 鎖定 ${features.length} 項功能 · ${durLabels[duration]}`,
              tone: "warn",
            });
            setLockUser(null);
          }}
        />
      )}
    </div>
  );
};

// --- audit log helper ---
const logAudit = (action, user, details = {}) => {
  let adminEmail = "unknown";
  try {
    adminEmail =
      localStorage.getItem("adminEmail") ||
      JSON.parse(localStorage.getItem("duidui_admin_state") || "{}").adminEmail ||
      "unknown";
  } catch {}
  fetch("/api/admin/audit", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      adminEmail,
      action,
      targetUserId: user?.id ?? null,
      targetUserName: user?.name ?? null,
      details,
    }),
  }).catch(() => {});
};

// --- helpers ---
const relativeJoinLabel = (dateStr) => {
  const d = new Date(dateStr);
  const diff = (Date.now() - d.getTime()) / (1000*60*60*24);
  if (diff < 7) return "本週加入";
  if (diff < 30) return `${Math.round(diff)} 天前`;
  const m = Math.round(diff / 30);
  return `${m} 個月前`;
};

const StatusBadge = ({ status }) => {
  const s = USER_STATUS[status] || USER_STATUS.active;
  return <Badge tone={s.tone} size="sm" dot>{s.label}</Badge>;
};

const Pagination = ({ total, pageSize, page = 0, onPageChange }) => {
  const totalPages = Math.ceil(total / pageSize) || 1;
  const start = page * pageSize + 1;
  const end = Math.min((page + 1) * pageSize, total);

  // Build visible page range (up to 5 buttons centred on current page)
  let lo = Math.max(0, page - 2);
  let hi = Math.min(totalPages - 1, lo + 4);
  lo = Math.max(0, hi - 4);
  const pages = [];
  for (let i = lo; i <= hi; i++) pages.push(i);

  const btnStyle = (active) => ({
    width: 30, height: 30, borderRadius: 6, fontSize: 13, cursor: "pointer",
    background: active ? "var(--ink)" : "transparent",
    color: active ? "#fff" : "var(--ink-2)",
    border: "1px solid " + (active ? "var(--ink)" : "var(--border)"),
  });

  return (
    <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginTop: 16, fontSize: 13, color: "var(--ink-3)" }}>
      <div>顯示 {total === 0 ? 0 : start} - {end} 共 {total} 筆</div>
      <div style={{ display: "flex", gap: 4, alignItems: "center" }}>
        <Button variant="secondary" size="sm" icon="chevron-left" disabled={page === 0} onClick={() => onPageChange?.(page - 1)}/>
        {lo > 0 && <>
          <button style={btnStyle(false)} onClick={() => onPageChange?.(0)}>1</button>
          {lo > 1 && <span style={{ padding: "0 4px", color: "var(--ink-4)" }}>…</span>}
        </>}
        {pages.map(p => (
          <button key={p} style={btnStyle(p === page)} onClick={() => onPageChange?.(p)}>{p + 1}</button>
        ))}
        {hi < totalPages - 1 && <>
          {hi < totalPages - 2 && <span style={{ padding: "0 4px", color: "var(--ink-4)" }}>…</span>}
          <button style={btnStyle(false)} onClick={() => onPageChange?.(totalPages - 1)}>{totalPages}</button>
        </>}
        <Button variant="secondary" size="sm" iconRight="chevron-right" disabled={page >= totalPages - 1} onClick={() => onPageChange?.(page + 1)}>下一頁</Button>
      </div>
    </div>
  );
};

// ============== USER DETAIL DRAWER ==============

const UserDetailDrawer = ({ user, violation, onClose, onAction, onReveal, flaggedUserIds }) => {
  const [tab, setTab] = useState("overview");
  const [auditLogs, setAuditLogs] = useState([]);
  const [auditLoading, setAuditLoading] = useState(false);
  const [apiViolation, setApiViolation] = useState(null);

  React.useEffect(() => {
    if (!user || tab !== "logs") return;
    setAuditLoading(true);
    fetch(`/api/admin/audit?userId=${user.id}&limit=30`)
      .then(r => r.ok ? r.json() : [])
      .then(d => { setAuditLogs(Array.isArray(d) ? d : []); setAuditLoading(false); })
      .catch(() => setAuditLoading(false));
  }, [user?.id, tab]);

  React.useEffect(() => {
    if (!user || tab !== "violations") return;
    fetch(`/api/admin/users/${user.id}/violation`)
      .then(r => r.ok ? r.json() : null)
      .then(d => { if (d) setApiViolation(d); })
      .catch(() => {});
  }, [user?.id, tab]);

  // Reset API violation when user changes
  React.useEffect(() => { setApiViolation(null); }, [user?.id]);

  if (!user) return null;
  const v = apiViolation || violation || { points: 0, entries: [], locks: null };
  const isArtist = user.role === "illustrator" || user.role === "author";
  const isBanned = user.status === "suspended";
  const isSuperAdmin = CURRENT_ROLE === "super_admin";

  // Synthesized per-user data
  const userOrders = MOCK.ORDERS.slice((user.id.charCodeAt(1) || 2) % 10, ((user.id.charCodeAt(1) || 2) % 10) + 6);
  const disputes = userOrders.filter(o => o.status === "disputed" || o.status === "refund_requested" || o.status === "refunded").slice(0, 3);
  // For suspended user show at least 2 disputes
  const shownDisputes = isBanned && disputes.length < 2
    ? [...disputes, ...MOCK.ORDERS.filter(o => o.status === "disputed").slice(0, 2 - disputes.length)]
    : disputes;
  const warningsCount = user.status === "warning" ? 1 : isBanned ? 3 : 0;

  return (
    <Drawer open={!!user} onClose={onClose} width={720}>
      <div style={{ padding: "18px 24px", borderBottom: "1px solid var(--border)", display: "flex", alignItems: "center", gap: 12 }}>
        <button onClick={onClose} style={{ padding: 4, color: "var(--ink-3)" }}><Icon name="x" size={18}/></button>
        <div style={{ fontSize: 13, color: "var(--ink-3)" }}>用戶詳情</div>
        <div style={{ flex: 1 }}/>
        <Button variant="ghost" size="sm" icon="mail" onClick={() => onAction("msg", user)}>發送站內信</Button>
        <Button variant="ghost" size="sm" icon="scroll">查看完整日誌</Button>
      </div>

      <div style={{ padding: "24px 28px 0", flexShrink: 0 }}>
        <div style={{ display: "flex", gap: 16, alignItems: "flex-start" }}>
          {user.avatar.url
            ? <img src={user.avatar.url} style={{ width: 64, height: 64, borderRadius: "50%", objectFit: "cover", flexShrink: 0 }}/>
            : <Avatar hue={user.avatar.hue} glyph={user.avatar.glyph} size={64}/>
          }
          <div style={{ flex: 1, minWidth: 0 }}>
            <div style={{ display: "flex", alignItems: "center", gap: 10, flexWrap: "wrap" }}>
              <h2 style={{ fontSize: 22, fontWeight: 600 }}>{user.name}</h2>
              <StatusBadge status={user.status}/>
              {user.kycVerified
                ? <Badge tone="success" size="sm"><Icon name="shield" size={11} style={{ marginRight: 3 }}/>成年已驗證</Badge>
                : <Badge tone="default" size="sm">未驗證成年</Badge>
              }
              {warningsCount > 0 && <Badge tone="warn" size="sm">違規 {warningsCount}</Badge>}
              {v.points > 0 && !v.locks && (
                <Badge tone={v.points >= 3 ? "danger" : v.points >= 2 ? "warn" : "default"} size="sm">
                  違規 {v.points}/3 點
                </Badge>
              )}
              {v.locks && <Badge tone="warn" size="sm" dot>功能鎖定中</Badge>}
            </div>
            <div style={{ fontSize: 13, color: "var(--ink-3)", marginTop: 4, display: "flex", gap: 10, flexWrap: "wrap" }}>
              <span className="mono">{user.uid ?? "—"}</span>
              <span>·</span>
              <span>{isArtist ? `創作者 · ${user.level}` : "委託人"}</span>
              <span>·</span>
              <span>加入於 {user.joinedAt} ({relativeJoinLabel(user.joinedAt)})</span>
            </div>
            {isArtist && user.tags?.length > 0 && (
              <div style={{ marginTop: 10, display: "flex", gap: 6, flexWrap: "wrap" }}>
                {user.tags.map(t => <Badge key={t} tone="default" size="sm">{t}</Badge>)}
              </div>
            )}
          </div>
        </div>

        {/* Banned banner */}
        {isBanned && (
          <div style={{ marginTop: 18, padding: "12px 14px", background: "var(--danger-soft)", border: "1px solid color-mix(in oklch, var(--danger) 20%, transparent)", borderRadius: 10, display: "flex", gap: 10, alignItems: "center" }}>
            <Icon name="ban" size={16} style={{ color: "var(--danger)" }}/>
            <div style={{ flex: 1, fontSize: 13 }}>
              <b style={{ color: "var(--danger)" }}>
                {user.bannedUntil ? "暫時封鎖" : "永久封鎖"}
              </b>
              {user.bannedUntil && (
                <span style={{ color: "var(--ink-2)", marginLeft: 8 }}>
                  · 至 {new Date(user.bannedUntil).toLocaleDateString("zh-TW", { year: "numeric", month: "2-digit", day: "2-digit" })}
                </span>
              )}
              {user.bannedReason && (
                <span style={{ color: "var(--ink-2)", marginLeft: 8 }}>· 原因：{user.bannedReason}</span>
              )}
            </div>
            <Button size="sm" variant="secondary" onClick={() => onAction("unban", user)}>解除封鎖</Button>
          </div>
        )}

        {/* Quick stats */}
        <div style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 0, marginTop: 20, border: "1px solid var(--border)", borderRadius: 10, overflow: "hidden" }}>
          {[
            { label: "訂單總數", value: user.orders, mono: true },
            { label: isArtist ? "總營收" : "總消費", value: fmtCurrency(isArtist ? user.revenue : user.spent || 0, false), prefix: "NT$" },
            { label: "評分", value: user.rating || "—", icon: "star" },
            { label: "違規紀錄", value: warningsCount, tone: warningsCount > 0 ? "warn" : "ink" },
          ].map((s, i) => (
            <div key={i} style={{ padding: "14px 16px", borderRight: i < 3 ? "1px solid var(--border)" : "none" }}>
              <div style={{ fontSize: 11.5, color: "var(--ink-3)", marginBottom: 4 }}>{s.label}</div>
              <div style={{ display: "flex", alignItems: "baseline", gap: 4 }}>
                {s.prefix && <span style={{ fontSize: 11, color: "var(--ink-3)" }}>{s.prefix}</span>}
                <div className="serif" style={{ fontSize: 20, lineHeight: 1, color: s.tone === "warn" ? "var(--warn)" : "var(--ink)" }}>{s.value}</div>
                {s.icon && s.value !== "—" && <Icon name={s.icon} size={12} style={{ color: "var(--warn)", marginLeft: 2 }}/>}
              </div>
            </div>
          ))}
        </div>

        <div style={{ marginTop: 20, marginBottom: -1 }}>
          <Tabs active={tab} onChange={setTab} tabs={[
            { value: "overview", label: "基本資訊" },
            { value: "orders", label: "訂單紀錄", count: user.orders },
            { value: "disputes", label: "糾紛紀錄", count: shownDisputes.length },
            { value: "violations", label: "違規計點", count: v.points, tone: v.points >= 3 ? "danger" : undefined },
            { value: "logs", label: "操作日誌" },
          ]}/>
        </div>
      </div>

      <div style={{ flex: 1, overflow: "auto", padding: "20px 28px 90px" }}>
        {tab === "overview" && (
          <div style={{ display: "flex", flexDirection: "column", gap: 20 }}>
            <InfoSection title="聯絡資訊">
              <InfoRow label="Email" value={<MaskedValue value={user.email} type="email" onReveal={cb => onReveal("email", user.id, cb)}/>}/>
              <InfoRow label="電話" value={<MaskedValue value={user.phone} type="phone" onReveal={cb => onReveal("phone", user.id, cb)}/>}/>
              <InfoRow label="加入日期" value={<span className="mono">{user.joinedAt}</span>}/>
              {isArtist && <InfoRow label="銀行帳號" value={<MaskedValue value={user.bankAccount} type="bank" onReveal={cb => onReveal("bank", user.id, cb)}/>}/>}
            </InfoSection>

            <InfoSection title="成年驗證">
              <InfoRow label="驗證狀態" value={
                user.kycVerified
                  ? <Badge tone="success" size="sm"><Icon name="check" size={11} style={{ marginRight: 3 }}/>已通過驗證</Badge>
                  : <Badge tone="default" size="sm">尚未驗證</Badge>
              }/>
              {user.kycVerified && (
                <InfoRow label="驗證日期" value={<span className="mono" style={{ color: "var(--ink-2)" }}>{user.joinedAt}</span>}/>
              )}
            </InfoSection>

            <InfoSection title="帳戶狀態">
              <InfoRow label="目前狀態" value={<StatusBadge status={user.status}/>}/>
              <InfoRow label="違規次數" value={
                <span style={{ color: warningsCount > 0 ? "var(--warn)" : "var(--ink-2)" }}>{warningsCount} 次</span>
              }/>
              {user.status === "warning" && <InfoRow label="最近警告" value="2 天前 · 作品版權疑慮"/>}
              {isBanned && <InfoRow label="封鎖期限" value={
                <span style={{ color: "var(--danger)" }}>
                  {user.bannedUntil
                    ? `至 ${new Date(user.bannedUntil).toLocaleDateString("zh-TW", { year: "numeric", month: "2-digit", day: "2-digit" })}`
                    : "永久封鎖"}
                </span>
              }/>}
              {isBanned && user.bannedReason && <InfoRow label="封鎖原因" value={<span style={{ color: "var(--ink-2)" }}>{user.bannedReason}</span>}/>}
              <InfoRow label="上次登入" value={<span style={{ color: "var(--ink-2)" }}>{user.lastLoginAt ? new Date(user.lastLoginAt).toLocaleString("zh-TW", { year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit" }) : "—"}</span>}/>
            </InfoSection>

            <InfoSection title="創作者身份">
              <InfoRow label="目前身份" value={
                isArtist
                  ? <div style={{ display: "flex", gap: 6 }}>
                      {user.role === "illustrator" && <Badge tone="accent" size="sm">繪師</Badge>}
                      {user.role === "author" && <Badge tone="info" size="sm">作者</Badge>}
                    </div>
                  : <span style={{ color: "var(--ink-3)", fontSize: 13 }}>尚未成為創作者</span>
              }/>
              <InfoRow label="個人邀請碼" value={
                <span className="mono" style={{ color: "var(--ink-2)", letterSpacing: 1 }}>
                  {user.inviteCode ?? "—"}
                </span>
              }/>
              {isArtist && (
                <InfoRow label="邀請名額使用" value={
                  <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
                    <div style={{ display: "flex", gap: 4 }}>
                      {[0,1,2].map(i => (
                        <div key={i} style={{
                          width: 10, height: 10, borderRadius: "50%",
                          background: i < (user.inviteUsesCount ?? 0) ? "var(--accent)" : "var(--border-strong)",
                        }}/>
                      ))}
                    </div>
                    <span style={{ fontSize: 12, color: "var(--ink-3)" }}>
                      已邀請 {user.inviteUsesCount ?? 0} / 3 人
                    </span>
                  </div>
                }/>
              )}
              {!isArtist && <SendCreatorInvitePanel user={user}/>}
            </InfoSection>
          </div>
        )}

        {tab === "orders" && (
          <div>
            <div style={{ display: "flex", gap: 10, fontSize: 12, color: "var(--ink-3)", marginBottom: 10 }}>
              <span>全部 {user.orders}</span><span>·</span>
              <span>進行中 4</span><span>·</span>
              <span>已完成 {user.orders - 4}</span>
            </div>
            <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
              {userOrders.map(o => <MiniOrderRow key={o.id} order={o}/>)}
            </div>
          </div>
        )}

        {tab === "disputes" && (
          <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
            {shownDisputes.length === 0 && (
              <div style={{ padding: "60px 0", textAlign: "center", color: "var(--ink-4)", fontSize: 13 }}>
                <Icon name="shield" size={28} style={{ color: "var(--success)", marginBottom: 10 }}/>
                <div>無糾紛紀錄</div>
                <div style={{ fontSize: 12, marginTop: 4 }}>這是一位乖巧的用戶 ✓</div>
              </div>
            )}
            {shownDisputes.map(o => <DisputeRow key={o.id} order={o}/>)}
          </div>
        )}

        {tab === "violations" && (
          <ViolationTab
            user={user}
            violationState={v}
            onAddPoint={() => onAction("addPoint", user)}
            onLockFeatures={() => onAction("lock", user)}
            onUnlock={() => onAction("unlock", user)}
            onDismissPoint={(entry) => onAction("dismissPoint", { user, entry, currentViolation: v })}
          />
        )}

        {tab === "logs" && (
          <div style={{ display: "flex", flexDirection: "column" }}>
            {auditLoading ? (
              <div style={{ padding: "40px 0", textAlign: "center", color: "var(--ink-4)", fontSize: 13 }}>載入中…</div>
            ) : auditLogs.length === 0 ? (
              <div style={{ padding: "60px 0", textAlign: "center", color: "var(--ink-4)", fontSize: 13 }}>
                <Icon name="scroll" size={24} style={{ marginBottom: 8 }}/>
                <div>尚無操作紀錄</div>
              </div>
            ) : auditLogs.map((l, i) => {
              const time = new Date(l.createdAt).toLocaleString("zh-TW", {
                year: "numeric", month: "2-digit", day: "2-digit",
                hour: "2-digit", minute: "2-digit",
              });
              const actionTone = {
                "永久封鎖": "danger", "暫時封鎖": "warn",
                "累計違規點數": "warn", "鎖定功能": "warn", "更新功能鎖定": "warn",
                "解除封鎖": "success", "強制登出": "default",
              }[l.action] || "default";
              const dotColor = { danger: "var(--danger)", warn: "var(--warn)", success: "var(--success)", default: "var(--ink-4)" }[actionTone];
              return (
                <div key={l.id} style={{ padding: "13px 0", borderTop: i > 0 ? "1px solid var(--border)" : "none", display: "flex", gap: 10 }}>
                  <div style={{ width: 8, height: 8, borderRadius: "50%", background: dotColor, marginTop: 5, flexShrink: 0 }}/>
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <div style={{ fontSize: 13 }}>
                      <b>{l.action}</b>
                      {l.details?.reason && <span style={{ color: "var(--ink-2)", marginLeft: 6 }}>· {l.details.reason}</span>}
                      {l.details?.duration && <span style={{ color: "var(--ink-3)", marginLeft: 6 }}>({l.details.duration})</span>}
                    </div>
                    <div style={{ fontSize: 11.5, color: "var(--ink-4)", marginTop: 2 }}>
                      {l.adminEmail} · {time}
                    </div>
                  </div>
                </div>
              );
            })}
          </div>
        )}
      </div>

      {/* Footer — 5 required actions */}
      <div style={{ padding: "14px 24px", borderTop: "1px solid var(--border)", background: "var(--surface-2)", display: "flex", gap: 8, flexWrap: "wrap" }}>
        <Button variant="secondary" icon="logout" onClick={() => onAction("logout", user)}>強制登出</Button>
        <Button
          variant="secondary"
          icon="flag"
          style={flaggedUserIds?.has(user.id) ? { color: "var(--warn)" } : {}}
          onClick={() => onAction("flag", user)}
        >
          {flaggedUserIds?.has(user.id) ? "取消標記" : "標記用戶"}
        </Button>
        <Button variant="secondary" onClick={() => onAction("addPoint", user)} style={{ color: v.points >= 2 ? "var(--danger)" : "var(--warn)" }}>
          <Icon name="alert" size={15}/> 累計違規
        </Button>
        <div style={{ flex: 1 }}/>
        {isBanned ? (
          <Button variant="primary" icon="shield" onClick={() => onAction("unban", user)}>解除封鎖</Button>
        ) : (
          <>
            <Button variant="secondary" onClick={() => onAction("tempBan", user)} style={{ color: "var(--warn)" }}>
              <Icon name="ban" size={15}/> 暫時封鎖
            </Button>
            <Button
              variant="danger"
              icon="shield"
              onClick={() => onAction("permBan", user)}
              disabled={!isSuperAdmin}
              title={!isSuperAdmin ? "僅 Super Admin 可執行" : ""}
            >
              永久封鎖
              {!isSuperAdmin && <Icon name="lock" size={12} style={{ marginLeft: 4, opacity: 0.7 }}/>}
            </Button>
          </>
        )}
      </div>
    </Drawer>
  );
};

// ============== Send Creator Invite ==============

const SendCreatorInvitePanel = ({ user }) => {
  const { useState: uS } = React;
  const [role, setRole] = uS("illustrator");
  const [loading, setLoading] = uS(false);
  const [sent, setSent] = uS(false);
  const [error, setError] = uS("");

  const send = async () => {
    setLoading(true); setError("");
    const adminEmail = localStorage.getItem("adminEmail") || "";
    const res = await fetch("/api/admin/users/send-invite", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ userId: user.id, role, adminEmail }),
    });
    setLoading(false);
    if (!res.ok) {
      const d = await res.json().catch(() => ({}));
      setError(d.error || "發送失敗");
    } else {
      setSent(true);
    }
  };

  if (sent) {
    return (
      <div style={{ padding: "10px 14px", fontSize: 13, color: "var(--success)", display: "flex", alignItems: "center", gap: 6 }}>
        <Icon name="check" size={14}/> 邀請碼已寄至 {user.email}
      </div>
    );
  }

  return (
    <div style={{ padding: "10px 14px", borderTop: "1px solid var(--border)" }}>
      <div style={{ fontSize: 12, color: "var(--ink-3)", marginBottom: 8 }}>寄送創作者審核邀請碼</div>
      <div style={{ display: "flex", gap: 8, marginBottom: 8 }}>
        {[["illustrator","繪師"],["author","作者"]].map(([val, label]) => (
          <button key={val} onClick={() => setRole(val)} style={{
            padding: "4px 12px", borderRadius: 6, fontSize: 12, fontWeight: 500,
            border: "1.5px solid " + (role === val ? "var(--accent)" : "var(--border)"),
            color: role === val ? "var(--accent-ink)" : "var(--ink-3)",
            background: role === val ? "var(--accent-soft)" : "transparent",
          }}>{label}</button>
        ))}
      </div>
      {error && <div style={{ fontSize: 12, color: "var(--danger)", marginBottom: 6 }}>{error}</div>}
      <Button variant="primary" size="sm" onClick={send} disabled={loading} style={{ width: "100%" }}>
        {loading ? "發送中…" : `發送邀請碼至 ${user.email}`}
      </Button>
    </div>
  );
};

// ============== Shared row components ==============

const InfoSection = ({ title, children }) => (
  <div>
    <div style={{ fontSize: 11.5, fontWeight: 600, color: "var(--ink-3)", letterSpacing: 0.8, textTransform: "uppercase", marginBottom: 10 }}>{title}</div>
    <div style={{ background: "var(--surface)", border: "1px solid var(--border)", borderRadius: 10, overflow: "hidden" }}>
      {children}
    </div>
  </div>
);
// backward-compat alias
const Section = InfoSection;

const InfoRow = ({ label, value }) => (
  <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", padding: "11px 14px", borderTop: "1px solid var(--border)", minHeight: 42 }}
    className="info-row"
  >
    <div style={{ fontSize: 12.5, color: "var(--ink-3)" }}>{label}</div>
    <div style={{ fontSize: 13, textAlign: "right" }}>{value}</div>
  </div>
);

const MiniOrderRow = ({ order }) => (
  <div style={{ display: "flex", alignItems: "center", gap: 12, padding: "12px 14px", border: "1px solid var(--border)", borderRadius: 10, background: "var(--surface)" }}>
    <div style={{ width: 36, height: 36, borderRadius: 8, background: "var(--surface-2)", display: "flex", alignItems: "center", justifyContent: "center", color: "var(--ink-3)" }}>
      <Icon name="order" size={16}/>
    </div>
    <div style={{ flex: 1, minWidth: 0 }}>
      <div style={{ fontSize: 13, fontWeight: 500 }}>{order.type} <span className="mono" style={{ color: "var(--ink-3)", fontWeight: 400, marginLeft: 6 }}>{order.id}</span></div>
      <div style={{ fontSize: 11.5, color: "var(--ink-3)", marginTop: 2 }}>{order.createdAt}</div>
    </div>
    <span className="mono" style={{ fontSize: 13 }}>{fmtCurrency(order.amount)}</span>
    <OrderStatusBadge status={order.status}/>
  </div>
);

const DisputeRow = ({ order }) => (
  <div style={{ padding: "14px", border: "1px solid var(--border)", borderRadius: 10, background: "var(--surface)", display: "flex", gap: 12 }}>
    <div style={{ width: 36, height: 36, borderRadius: 8, background: "var(--danger-soft)", color: "var(--danger)", display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0 }}>
      <Icon name="alert" size={16}/>
    </div>
    <div style={{ flex: 1, minWidth: 0 }}>
      <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 4 }}>
        <span style={{ fontSize: 13, fontWeight: 500 }}>糾紛 · {order.type}</span>
        <span className="mono" style={{ fontSize: 11.5, color: "var(--ink-3)" }}>{order.id}</span>
        <OrderStatusBadge status={order.status}/>
      </div>
      <div style={{ fontSize: 12.5, color: "var(--ink-2)" }}>爭議理由:交付內容與需求不符,要求全額退款</div>
      <div style={{ fontSize: 11.5, color: "var(--ink-4)", marginTop: 4 }}>提交於 {order.createdAt} · 處理中 · 金額 {fmtCurrency(order.amount)}</div>
    </div>
    <Button size="sm" variant="secondary">查看</Button>
  </div>
);

const OrderStatusBadge = ({ status }) => {
  const map = {
    draft: { label: "草稿", tone: "default" },
    in_progress: { label: "進行中", tone: "info" },
    review: { label: "審核中", tone: "warn" },
    completed: { label: "已完成", tone: "success" },
    refund_requested: { label: "退款中", tone: "warn" },
    refunded: { label: "已退款", tone: "default" },
    disputed: { label: "糾紛中", tone: "danger" },
  };
  const s = map[status] || map.draft;
  return <Badge tone={s.tone} size="sm" dot>{s.label}</Badge>;
};

Object.assign(window, { UsersPage, UserDetailDrawer, OrderStatusBadge, MiniOrderRow, Section, InfoSection, InfoRow, Pagination, StatusBadge });
