import { useEffect, useState } from "react";
import { Link, Navigate } from "react-router-dom";
import { useAuth } from "../auth/AuthContext";
import { PageHeader } from "../components/layout/PageHeader";
import { Badge, Button, Card, EmptyState, Input, Pager, Select } from "../components/ui";
import { useData, useRepos } from "../data/DataContext";
import type { Role } from "../domain/types";
import { useI18n } from "../i18n/I18nContext";
import { memberRoleSummary, roleLabel } from "../lib/memberRole";
import type { MemberAdminView } from "../lib/tenantUsers";
import { firstRunStatusLabelKey, firstRunStatusTone } from "../lib/firstRunStatus";
import { useFormatApiError } from "../lib/apiErrors";
import { checkPasswordPolicy, isPasswordPolicyOk } from "../lib/passwordPolicy";
import { formatLocalDateTime, nowUnixNano } from "../lib/time";
import { PLANS, type PlanId, type UsageMemberPrefs } from "../lib/usageMeter";

const PAGE_SIZE_OPTIONS = [5, 10, 20];

/** 最近揭示的臨時密碼只保留在記憶體，不寫入瀏覽器儲存空間。 */
type RevealedTempPassword = {
  uid: string;
  display_name: string;
  email: string;
  password: string;
  created_at: number;
  reason?: "create" | "reset";
};

/**
 * 管理員：島民列表（搜尋名稱／uid）+ 新增、停權、權限、驗證、重設密碼。
 */
export function AdminUsersPage() {
  const repos = useRepos();
  const { member, reload } = useAuth();
  const { t } = useI18n();
  const formatApiError = useFormatApiError();
  const { tick, refresh } = useData();
  const [users, setUsers] = useState<MemberAdminView[]>([]);
  const [page, setPage] = useState(1);
  const [pageSize, setPageSize] = useState(10);
  const [total, setTotal] = useState(0);
  const [query, setQuery] = useState("");
  const [queryDraft, setQueryDraft] = useState("");
  const [selected, setSelected] = useState<MemberAdminView | null>(null);
  const [roleDraft, setRoleDraft] = useState<Role[]>(["member"]);
  const [busy, setBusy] = useState("");
  const [message, setMessage] = useState("");
  const [error, setError] = useState("");
  const [revealed, setRevealed] = useState<RevealedTempPassword | null>(null);
  const [copyHint, setCopyHint] = useState("");
  const [customPw, setCustomPw] = useState("");

  const [showCreate, setShowCreate] = useState(false);
  const [createName, setCreateName] = useState("");
  const [createEmail, setCreateEmail] = useState("");
  const [createPassword, setCreatePassword] = useState("");
  const [createVerified, setCreateVerified] = useState(true);
  const [createAsAdmin, setCreateAsAdmin] = useState(false);
  /** 選中島民的方案／不擋額度 */
  const [usagePrefs, setUsagePrefs] = useState<UsageMemberPrefs | null>(null);

  const isAdmin = memberRoleSummary(member, t).isAdmin;

  useEffect(() => {
    if (!isAdmin) return;
    void (async () => {
      try {
        const res = await repos.adminUsers.listUsersPage({
          page,
          pageSize,
          query,
        });
        setUsers(res.list);
        setTotal(res.total);
        setPage(res.page);
      } catch (e) {
        setError(formatApiError(e, "admin.users.loadFail"));
      }
    })();
  }, [repos.adminUsers, tick, isAdmin, page, pageSize, query, formatApiError]);

  const selectedUid = selected?.uid ?? "";
  const selectedRolesKey = selected?.roles?.slice().sort().join(",") ?? "";

  useEffect(() => {
    if (!selectedUid || !selected) return;
    setRoleDraft(selected.roles.includes("admin") ? ["member", "admin"] : ["member"]);
    // eslint-disable-next-line react-hooks/exhaustive-deps -- selectedRolesKey tracks role changes
  }, [selectedUid, selectedRolesKey]);

  useEffect(() => {
    if (!selectedUid || !isAdmin) {
      setUsagePrefs(null);
      return;
    }
    void repos.usage.getMemberPrefs(selectedUid).then(setUsagePrefs).catch(() => setUsagePrefs(null));
  }, [selectedUid, isAdmin, repos.usage, tick]);

  // 路由已包 RequireAdmin；此處僅防守
  if (!member) return <Navigate to="/login" replace />;
  if (!isAdmin) return <Navigate to="/app/today" replace />;

  async function reloadList() {
    const res = await repos.adminUsers.listUsersPage({ page, pageSize, query });
    setUsers(res.list);
    setTotal(res.total);
    setPage(res.page);
    if (selected) {
      const u = await repos.adminUsers.getUser(selected.uid);
      setSelected(u);
    }
    refresh();
  }

  async function createMember() {
    setBusy("create");
    setMessage("");
    setError("");
    setCopyHint("");
    const pw = createPassword.trim();
    if (pw) {
      const policy = checkPasswordPolicy(pw);
      if (!policy.ok) {
        setError(t(policy.errorKey || "password.policy.hint"));
        setBusy("");
        return;
      }
    }
    try {
      const res = await repos.adminUsers.createMember({
        display_name: createName,
        email: createEmail,
        password: pw || undefined,
        roles: createAsAdmin ? ["member", "admin"] : ["member"],
        email_verified: createVerified,
      });
      const rec: RevealedTempPassword = {
        uid: res.user.uid,
        display_name: res.user.display_name,
        email: res.user.email,
        password: res.temporary_password,
        created_at: nowUnixNano(),
        reason: "create",
      };
      setRevealed(rec);
      setCreateName("");
      setCreateEmail("");
      setCreatePassword("");
      setCreateVerified(true);
      setCreateAsAdmin(false);
      setShowCreate(false);
      setSelected(res.user);
      setQuery("");
      setQueryDraft("");
      setPage(1);
      setMessage(t("admin.users.created", { name: res.user.display_name }));
      await reloadList();
    } catch (e) {
      setError(formatApiError(e, "admin.users.createFail"));
    } finally {
      setBusy("");
    }
  }

  async function saveUsageUnlimited(unlimited: boolean) {
    if (!selected) return;
    setBusy(`usage:${selected.uid}`);
    setMessage("");
    setError("");
    try {
      const next = await repos.usage.setMemberPrefs(selected.uid, { unlimited });
      setUsagePrefs(next);
      setMessage(
        unlimited
          ? t("admin.users.unlimitedOn", { name: selected.display_name })
          : t("admin.users.unlimitedOff", { name: selected.display_name }),
      );
    } catch (e) {
      setError(formatApiError(e, "admin.users.updateFail"));
    } finally {
      setBusy("");
    }
  }

  async function saveUsagePlan(plan_id: PlanId) {
    if (!selected) return;
    setBusy(`usage:${selected.uid}`);
    setMessage("");
    setError("");
    try {
      const next = await repos.usage.setMemberPrefs(selected.uid, { plan_id });
      setUsagePrefs(next);
      setMessage(t("admin.users.planSet", { name: selected.display_name, plan: PLANS[plan_id].name }));
    } catch (e) {
      setError(formatApiError(e, "admin.users.updateFail"));
    } finally {
      setBusy("");
    }
  }

  async function toggleSuspended(u: MemberAdminView) {
    const willSuspend = u.status !== "suspended";
    if (
      !window.confirm(
        willSuspend
          ? t("admin.users.confirmSuspend", { name: u.display_name })
          : t("admin.users.confirmUnsuspend", { name: u.display_name }),
      )
    ) {
      return;
    }
    setBusy(`suspend:${u.uid}`);
    setMessage("");
    setError("");
    try {
      const next = await repos.adminUsers.setSuspended(u.uid, willSuspend);
      setMessage(
        willSuspend
          ? t("admin.users.didSuspend", { name: next.display_name })
          : t("admin.users.didUnsuspend", { name: next.display_name }),
      );
      setSelected(next);
      await reloadList();
    } catch (e) {
      setError(
        formatApiError(
          e,
          willSuspend ? "admin.users.suspendFail" : "admin.users.unsuspendFail",
        ),
      );
    } finally {
      setBusy("");
    }
  }

  async function toggleVerified(u: MemberAdminView) {
    setBusy(`verify:${u.uid}`);
    setMessage("");
    setError("");
    try {
      const next = await repos.adminUsers.setEmailVerified(u.uid, !u.email_verified);
      setMessage(
        next.email_verified
          ? t("admin.users.markedVerified", { name: next.display_name })
          : t("admin.users.markedUnverified", { name: next.display_name }),
      );
      if (member?.uid === u.uid) await reload();
      await reloadList();
    } catch (e) {
      setError(formatApiError(e, "admin.users.updateFail"));
    } finally {
      setBusy("");
    }
  }

  async function saveRoles(u: MemberAdminView) {
    setBusy(`roles:${u.uid}`);
    setMessage("");
    setError("");
    try {
      const next = await repos.adminUsers.setRoles(u.uid, roleDraft);
      setMessage(
        t("admin.users.rolesUpdated", {
          name: next.display_name,
          roles: next.roles.map((r) => roleLabel(r, t)).join(t("common.listSep")),
        }),
      );
      if (member?.uid === u.uid) await reload();
      await reloadList();
    } catch (e) {
      setError(formatApiError(e, "admin.users.rolesFail"));
    } finally {
      setBusy("");
    }
  }

  async function doReset(u: MemberAdminView, useCustom: boolean) {
    if (
      !window.confirm(t("admin.users.confirmReset", { name: u.display_name }))
    ) {
      return;
    }
    if (useCustom) {
      const policy = checkPasswordPolicy(customPw.trim());
      if (!policy.ok) {
        setError(t(policy.errorKey || "password.policy.hint"));
        return;
      }
    }
    setBusy(`reset:${u.uid}`);
    setMessage("");
    setError("");
    setCopyHint("");
    try {
      const res = await repos.adminUsers.resetPassword(
        u.uid,
        useCustom ? customPw.trim() || undefined : undefined,
      );
      const rec: RevealedTempPassword = {
        uid: res.user.uid,
        display_name: res.user.display_name,
        email: res.user.email,
        password: res.temporary_password,
        created_at: nowUnixNano(),
        reason: "reset",
      };
      setRevealed(rec);
      setCustomPw("");
      setMessage(t("admin.users.resetDone", { name: res.user.display_name }));
      await reloadList();
    } catch (e) {
      setError(formatApiError(e, "admin.users.resetFail"));
    } finally {
      setBusy("");
    }
  }

  async function copyTempPassword() {
    if (!revealed?.password) return;
    try {
      await navigator.clipboard.writeText(revealed.password);
      setCopyHint(t("admin.users.copied"));
      window.setTimeout(() => setCopyHint(""), 2500);
    } catch {
      try {
        const ta = document.createElement("textarea");
        ta.value = revealed.password;
        ta.style.position = "fixed";
        ta.style.left = "-9999px";
        document.body.appendChild(ta);
        ta.select();
        document.execCommand("copy");
        document.body.removeChild(ta);
        setCopyHint(t("admin.users.copied"));
        window.setTimeout(() => setCopyHint(""), 2500);
      } catch {
        setCopyHint(t("admin.users.copyFail"));
      }
    }
  }

  function dismissTempPassword() {
    if (
      !window.confirm(t("admin.users.confirmDismissTemp"))
    ) {
      return;
    }
    setRevealed(null);
    setCopyHint("");
  }

  function applySearch() {
    setPage(1);
    setQuery(queryDraft.trim());
  }

  const isSuspended = selected?.status === "suspended";

  return (
    <>
      <PageHeader title={t("admin.users.title")} />

      {message ? (
        <p className="hb-banner-ok" role="status">
          {message}
        </p>
      ) : null}
      {error ? (
        <p className="hb-form-error" role="alert">
          {error}
        </p>
      ) : null}
      {revealed ? (
        <div className="hb-admin-temp-pw" role="status">
          <div className="hb-admin-temp-pw__head">
            <p className="hb-field__label" style={{ margin: 0 }}>
              {revealed.reason === "create" ? t("admin.users.tempPwNew") : t("admin.users.tempPw")}
              {t("admin.users.tempPwPersist")}
            </p>
            <span className="text-muted" style={{ fontSize: "var(--hb-text-xs)" }}>
              {revealed.display_name} · {revealed.email}
              {" · "}
              {formatLocalDateTime(revealed.created_at)}
            </span>
          </div>
          <div className="hb-admin-temp-pw__row">
            <code className="hb-admin-temp-pw__code" id="hb-admin-temp-pw-value">
              {revealed.password}
            </code>
            <div className="hb-admin-temp-pw__actions">
              <Button type="button" onClick={() => void copyTempPassword()}>
                {t("admin.users.copyPw")}
              </Button>
              <Button type="button" variant="ghost" onClick={dismissTempPassword}>
                {t("admin.users.close")}
              </Button>
            </div>
          </div>
          {copyHint ? (
            <p className="text-muted" style={{ margin: 0, fontSize: "var(--hb-text-xs)" }}>
              <strong style={{ color: "var(--hb-brand)" }}>{copyHint}</strong>
            </p>
          ) : null}
        </div>
      ) : null}

      <div className="hb-admin-create-bar">
        <Button
          type="button"
          variant={showCreate ? "ghost" : "primary"}
          onClick={() => {
            setShowCreate((v) => !v);
            setError("");
          }}
        >
          {showCreate ? t("common.cancel") : t("admin.users.create")}
        </Button>
      </div>

      {showCreate ? (
        <Card title={t("admin.users.createTitle")}>
          <div className="hb-admin-create-form">
            <Input
              label={t("admin.users.memberName")}
              value={createName}
              onChange={(e) => setCreateName(e.target.value)}
              placeholder={t("admin.users.displayNamePh")}
              autoComplete="off"
            />
            <Input
              label={t("admin.users.email")}
              type="email"
              value={createEmail}
              onChange={(e) => setCreateEmail(e.target.value)}
              placeholder="name@example.com"
              autoComplete="off"
            />
            <Input
              label={t("admin.users.initPassword")}
              type="password"
              value={createPassword}
              onChange={(e) => setCreatePassword(e.target.value)}
              placeholder={t("admin.users.initPasswordPh")}
              autoComplete="new-password"
            />
            <div className="hb-admin-create-checks">
              <label className="hb-check-row">
                <input
                  type="checkbox"
                  checked={createVerified}
                  onChange={(e) => setCreateVerified(e.target.checked)}
                />
                <span>{t("admin.users.markVerifiedCheck")}</span>
              </label>
              <label className="hb-check-row">
                <input
                  type="checkbox"
                  checked={createAsAdmin}
                  onChange={(e) => setCreateAsAdmin(e.target.checked)}
                />
                <span>{t("admin.users.alsoAdmin")}</span>
              </label>
            </div>
            <div className="hb-admin-actions">
              <Button
                type="button"
                disabled={Boolean(busy) || !createName.trim() || !createEmail.trim()}
                onClick={() => void createMember()}
              >
                {busy === "create" ? t("admin.users.creating") : t("admin.users.createSubmit")}
              </Button>
            </div>
          </div>
        </Card>
      ) : null}

      <div className="hb-admin-users">
        <Card title={t("admin.users.list", { n: total })}>
          <div className="hb-stack">
            <div className="hb-admin-search">
              <Input
                label={t("admin.users.search")}
                value={queryDraft}
                onChange={(e) => setQueryDraft(e.target.value)}
                placeholder={t("admin.users.searchPh")}
                onKeyDown={(e) => {
                  if (e.key === "Enter") {
                    e.preventDefault();
                    applySearch();
                  }
                }}
              />
              <Button type="button" onClick={applySearch}>
                {t("common.search")}
              </Button>
              {query ? (
                <Button
                  type="button"
                  variant="ghost"
                  onClick={() => {
                    setQueryDraft("");
                    setQuery("");
                    setPage(1);
                  }}
                >
                  {t("admin.users.clear")}
                </Button>
              ) : null}
            </div>
            {query ? (
              <p className="text-muted" style={{ margin: 0, fontSize: "var(--hb-text-xs)" }}>
                {t("admin.users.searchActive", { query })}
              </p>
            ) : null}

            {users.length === 0 ? (
              <EmptyState title={query ? t("admin.users.noMatch") : t("admin.users.none")} />
            ) : (
              <ul className="hb-admin-user-list">
                {users.map((u) => {
                  const role = memberRoleSummary(u, t);
                  const active = selected?.uid === u.uid;
                  const suspended = u.status === "suspended";
                  return (
                    <li key={u.uid}>
                      <button
                        type="button"
                        className={`hb-admin-user-row${active ? " is-active" : ""}${suspended ? " is-suspended" : ""}`}
                        onClick={() => {
                          setSelected(u);
                          setError("");
                        }}
                      >
                        <div className="hb-admin-user-row__main">
                          <strong>{u.display_name}</strong>
                          <span className="text-muted">{u.email}</span>
                          <span className="hb-admin-user-row__uid text-muted">
                            {u.invite_code ? `${u.invite_code} · ` : ""}
                            uid · {u.uid}
                          </span>
                        </div>
                        <div className="hb-admin-user-row__tags">
                          {suspended ? (
                            <Badge tone="danger">{t("admin.users.suspended")}</Badge>
                          ) : null}
                          <Badge tone={role.isAdmin ? "brand" : "neutral"}>
                            {role.primaryLabel}
                          </Badge>
                          <Badge tone={u.email_verified ? "success" : "warning"}>
                            {u.email_verified ? t("role.verified") : t("role.unverified")}
                          </Badge>
                          <Badge tone={firstRunStatusTone(u.onboarding_status)}>
                            {t(firstRunStatusLabelKey(u.onboarding_status))}
                          </Badge>
                        </div>
                      </button>
                    </li>
                  );
                })}
              </ul>
            )}

            <Pager
              total={total}
              page={page}
              pageSize={pageSize}
              onPageChange={setPage}
              onPageSizeChange={setPageSize}
              pageSizeOptions={PAGE_SIZE_OPTIONS}
              showWhenSingle
            />
          </div>
        </Card>

        <Card title={t("admin.users.detail")}>
          {!selected ? (
            <p className="text-muted" style={{ margin: 0 }}>
              {t("admin.users.pick")}
            </p>
          ) : (
            <div className="hb-stack">
              <div className="hb-admin-detail-head">
                <div>
                  <h2 className="hb-admin-detail-name">{selected.display_name}</h2>
                  <p className="text-muted" style={{ margin: "0.2rem 0 0" }}>
                    {selected.email}
                  </p>
                  <p style={{ margin: "0.35rem 0 0" }}>
                    <Link to="/app/invite" className="text-muted" style={{ fontSize: "var(--hb-text-xs)" }}>
                      {t("invite.openFromAdmin")}
                    </Link>
                  </p>
                </div>
                <div className="hb-inline-badges">
                  {selected.uid === member.uid ? <Badge tone="brand">{t("admin.users.you")}</Badge> : null}
                  {isSuspended ? (
                    <Badge tone="danger">{t("admin.users.suspended")}</Badge>
                  ) : (
                    <Badge tone="success">{t("admin.users.active")}</Badge>
                  )}
                </div>
              </div>

              <dl className="hb-admin-dl">
                <div>
                  <dt>{t("admin.users.status")}</dt>
                  <dd>{isSuspended ? t("admin.users.suspended") : t("admin.users.active")}</dd>
                </div>
                <div>
                  <dt>{t("admin.users.onboarding")}</dt>
                  <dd>
                    <Badge tone={firstRunStatusTone(selected.onboarding_status)}>
                      {t(firstRunStatusLabelKey(selected.onboarding_status))}
                    </Badge>
                  </dd>
                </div>
                <div>
                  <dt>{t("admin.users.role")}</dt>
                  <dd>{selected.roles.map((r) => roleLabel(r, t)).join(t("common.listSep"))}</dd>
                </div>
                <div>
                  <dt>{t("invite.codeLabel")}</dt>
                  <dd>
                    <code className="hb-admin-invite-line">
                      {selected.invite_code || t("common.dash")}
                    </code>
                  </dd>
                </div>
                <div>
                  <dt>{t("invite.parentField")}</dt>
                  <dd>
                    {selected.parent_uid ? (
                      <code>{selected.parent_uid}</code>
                    ) : (
                      t("invite.root")
                    )}
                  </dd>
                </div>
                <div>
                  <dt>{t("admin.users.emailVerify")}</dt>
                  <dd>
                    {selected.email_verified ? t("role.verified") : t("role.unverified")}
                  </dd>
                </div>
                <div>
                  <dt>{t("admin.users.bio")}</dt>
                  <dd>{selected.bio?.trim() || t("common.dash")}</dd>
                </div>
                <div>
                  <dt>{t("admin.users.timezone")}</dt>
                  <dd>{selected.timezone || t("common.dash")}</dd>
                </div>
                <div>
                  <dt>{t("admin.users.notifyEmail")}</dt>
                  <dd>{selected.notify_email ? t("admin.users.on") : t("admin.users.off")}</dd>
                </div>
                <div>
                  <dt>uid</dt>
                  <dd>
                    <code>{selected.uid}</code>
                  </dd>
                </div>
                <div>
                  <dt>{t("admin.users.createdAt")}</dt>
                  <dd>{formatLocalDateTime(selected.created_at)}</dd>
                </div>
                <div>
                  <dt>{t("admin.users.updatedAt")}</dt>
                  <dd>{formatLocalDateTime(selected.updated_at)}</dd>
                </div>
              </dl>

              {/* 停權 */}
              <div className="hb-admin-suspend">
                <p className="hb-field__label" style={{ margin: 0 }}>
                  {t("admin.users.accountStatus")}
                </p>
                <Button
                  type="button"
                  variant={isSuspended ? "secondary" : "danger"}
                  disabled={Boolean(busy) || selected.uid === member.uid}
                  onClick={() => void toggleSuspended(selected)}
                >
                  {busy === `suspend:${selected.uid}`
                    ? t("admin.users.updating")
                    : isSuspended
                      ? t("admin.users.unsuspend")
                      : t("admin.users.suspend")}
                </Button>
              </div>

              {/* 用量：方案 + 不擋額度（live 後端 M3 才有） */}
              <div className="hb-admin-usage">
                <p className="hb-field__label" style={{ margin: 0 }}>
                  {t("admin.users.usageTitle")}
                </p>
                {usagePrefs ? (
                  <>
                    <div className="hb-admin-usage__row">
                      <Select
                        label={t("admin.users.plan")}
                        value={usagePrefs.plan_id}
                        disabled={Boolean(busy) || isSuspended}
                        onChange={(e) => void saveUsagePlan(e.target.value as PlanId)}
                      >
                        {(Object.keys(PLANS) as PlanId[]).map((id) => (
                          <option key={id} value={id}>
                            {t("admin.users.planOption", {
                              name: PLANS[id].name,
                              credits: PLANS[id].monthly_credits,
                            })}
                          </option>
                        ))}
                      </Select>
                      {usagePrefs.unlimited ? (
                        <Badge tone="brand">{t("admin.users.unlimited")}</Badge>
                      ) : (
                        <Badge tone="neutral">{t("admin.users.byPlan")}</Badge>
                      )}
                    </div>
                    <Button
                      type="button"
                      variant={usagePrefs.unlimited ? "secondary" : "primary"}
                      disabled={Boolean(busy) || isSuspended}
                      onClick={() => void saveUsageUnlimited(!usagePrefs.unlimited)}
                    >
                      {busy === `usage:${selected.uid}`
                        ? t("admin.users.updating")
                        : usagePrefs.unlimited
                          ? t("admin.users.setLimited")
                          : t("admin.users.setUnlimited")}
                    </Button>
                    <p className="text-muted" style={{ margin: 0, fontSize: "var(--hb-text-xs)" }}>
                      {t("admin.users.unlimitedHint")}
                    </p>
                  </>
                ) : (
                  <p className="text-muted" style={{ margin: 0, fontSize: "var(--hb-text-sm)" }}>
                    {t("admin.users.loadingUsage")}
                  </p>
                )}
              </div>

              {/* 權限 */}
              <div className="hb-admin-roles">
                <p className="hb-field__label" style={{ margin: 0 }}>
                  {t("admin.users.assignRoles")}
                </p>
                <label className="hb-check-row">
                  <input
                    type="checkbox"
                    checked={roleDraft.includes("member")}
                    disabled
                    readOnly
                  />
                  <span>{t("admin.users.memberBase", { role: t("role.member") })}</span>
                </label>
                <label className="hb-check-row">
                  <input
                    type="checkbox"
                    checked={roleDraft.includes("admin")}
                    onChange={(e) => {
                      if (e.target.checked) {
                        setRoleDraft(["member", "admin"]);
                      } else {
                        setRoleDraft(["member"]);
                      }
                    }}
                  />
                  <span>{t("admin.users.adminDesc", { role: t("role.admin") })}</span>
                </label>
                <Button
                  type="button"
                  disabled={Boolean(busy) || isSuspended}
                  onClick={() => void saveRoles(selected)}
                >
                  {busy === `roles:${selected.uid}` ? t("admin.users.saving") : t("admin.users.saveRoles")}
                </Button>
              </div>

              <div className="hb-admin-actions">
                <Button
                  type="button"
                  variant={selected.email_verified ? "ghost" : "primary"}
                  disabled={Boolean(busy)}
                  onClick={() => void toggleVerified(selected)}
                >
                  {busy === `verify:${selected.uid}`
                    ? t("admin.users.updating")
                    : selected.email_verified
                      ? t("admin.users.markUnverifiedBtn")
                      : t("admin.users.markVerifiedBtn")}
                </Button>
                <Button
                  type="button"
                  variant="danger"
                  disabled={Boolean(busy) || isSuspended}
                  onClick={() => void doReset(selected, false)}
                >
                  {busy === `reset:${selected.uid}` ? t("admin.users.resetting") : t("admin.users.resetTemp")}
                </Button>
              </div>

              <div className="hb-admin-custom-pw">
                <Input
                  label={t("admin.users.customPw")}
                  type="password"
                  value={customPw}
                  onChange={(e) => setCustomPw(e.target.value)}
                  placeholder={t("admin.users.customPwPh")}
                  disabled={isSuspended}
                />
                <Button
                  type="button"
                  variant="ghost"
                  disabled={Boolean(busy) || isSuspended || !isPasswordPolicyOk(customPw.trim())}
                  onClick={() => void doReset(selected, true)}
                >
                  {t("admin.users.resetWithCustom")}
                </Button>
              </div>
            </div>
          )}
        </Card>
      </div>
    </>
  );
}
