// BEGIN CHANGE: admin wipe/reset - players + accounts + restore PP from BP
"use client";

import { useCallback, useEffect, useMemo, useState } from "react";
import { apiUrl } from "@/lib/api";
import { AdminConfirmModal } from "./AdminConfirmModal";
import { fmtTs } from "./types";

type Skills = {
  fist: number;
  club: number;
  sword: number;
  axe: number;
  distance: number;
  shielding: number;
  fishing: number;
};

type WipePlayer = {
  id: number;
  name: string;
  level: number;
  experience: number;
  magic: number;
  vocationId: number;
  groupId: number;
  salvar: number;
  reset: number;
  online: boolean;
  deleted: boolean;
  lastlogin: number;
  accountId: number;
  accountName: string;
  premiumPoints: number;
  backupPoints: number;
  guildPoints: number;
  pageAccess: number;
  skills: Skills;
};

type WipeAccount = {
  id: number;
  name: string;
  email: string;
  pageAccess: number;
  blocked: boolean;
  created: number;
  premiumPoints: number;
  backupPoints: number;
  guildPoints: number;
  recoveredPoints: number;
  playerCount: number;
  onlineCount: number;
  ppDiffersBackup: boolean;
};

type PlayerFilters = {
  name: string;
  account: string;
  salvar: string;
  groupId: string;
  pageAccess: string;
  levelMin: string;
  levelMax: string;
  resetMin: string;
  resetMax: string;
  online: string;
  deleted: string;
  premiumMin: string;
  backupMin: string;
  guildPointsMin: string;
};

type AccountFilters = {
  account: string;
  email: string;
  pageAccess: string;
  blocked: string;
  premiumMin: string;
  backupMin: string;
  guildPointsMin: string;
  hasPlayers: string;
  ppDiffersBackup: string;
};

const emptyPlayerFilters: PlayerFilters = {
  name: "",
  account: "",
  salvar: "",
  groupId: "",
  pageAccess: "",
  levelMin: "",
  levelMax: "",
  resetMin: "",
  resetMax: "",
  online: "",
  deleted: "0",
  premiumMin: "",
  backupMin: "",
  guildPointsMin: "",
};

const emptyAccountFilters: AccountFilters = {
  account: "",
  email: "",
  pageAccess: "",
  blocked: "",
  premiumMin: "",
  backupMin: "1",
  guildPointsMin: "",
  hasPlayers: "",
  ppDiffersBackup: "",
};

type Tab = "players" | "accounts";

type Pending =
  | { kind: "delete_selected" }
  | { kind: "delete_except_keep" }
  | { kind: "zero_guild_all" }
  | { kind: "zero_guild_selected" }
  | { kind: "restore_pp_selected" }
  | { kind: "restore_pp_filtered" }
  | { kind: "restore_pp_all_backup" };

function qsPlayer(f: PlayerFilters, page: number, pageSize: number): string {
  const p = new URLSearchParams();
  p.set("tool", "wipe_players");
  p.set("page", String(page));
  p.set("pageSize", String(pageSize));
  (Object.keys(f) as (keyof PlayerFilters)[]).forEach((k) => {
    const v = f[k].trim();
    if (v !== "") p.set(k, v);
  });
  return p.toString();
}

function qsAccount(f: AccountFilters, page: number, pageSize: number): string {
  const p = new URLSearchParams();
  p.set("tool", "wipe_accounts");
  p.set("page", String(page));
  p.set("pageSize", String(pageSize));
  (Object.keys(f) as (keyof AccountFilters)[]).forEach((k) => {
    const v = f[k].trim();
    if (v !== "") p.set(k, v);
  });
  return p.toString();
}

function numKeysPayload(
  f: Record<string, string>,
  numericKeys: string[],
): Record<string, string | number> {
  const out: Record<string, string | number> = {};
  Object.keys(f).forEach((k) => {
    const v = f[k].trim();
    if (v === "") return;
    out[k] = numericKeys.includes(k) ? Number(v) : v;
  });
  return out;
}

export function AdminWipePlayers({
  token,
  canUse,
}: {
  token: string;
  canUse: boolean;
}) {
  const [tab, setTab] = useState<Tab>("players");
  const [pageSize] = useState(100);
  const [busy, setBusy] = useState(false);
  const [err, setErr] = useState("");
  const [note, setNote] = useState("");
  const [pending, setPending] = useState<Pending | null>(null);
  const [lastResult, setLastResult] = useState<unknown>(null);

  // players
  const [pFilters, setPFilters] = useState<PlayerFilters>(emptyPlayerFilters);
  const [pApplied, setPApplied] = useState<PlayerFilters>(emptyPlayerFilters);
  const [pPage, setPPage] = useState(1);
  const [players, setPlayers] = useState<WipePlayer[]>([]);
  const [pTotal, setPTotal] = useState(0);
  const [pPages, setPPages] = useState(0);
  const [pSelected, setPSelected] = useState<Record<number, boolean>>({});

  // accounts
  const [aFilters, setAFilters] = useState<AccountFilters>(emptyAccountFilters);
  const [aApplied, setAApplied] = useState<AccountFilters>(emptyAccountFilters);
  const [aPage, setAPage] = useState(1);
  const [accounts, setAccounts] = useState<WipeAccount[]>([]);
  const [aTotal, setATotal] = useState(0);
  const [aPages, setAPages] = useState(0);
  const [aSelected, setASelected] = useState<Record<number, boolean>>({});

  // BEGIN CHANGE: item 11 - edicao de dados da conta (email/senha/nome) na tela Wipe/Reset
  const [editAcc, setEditAcc] = useState<WipeAccount | null>(null);
  const [eEmail, setEEmail] = useState("");
  const [ePass, setEPass] = useState("");
  const [eName, setEName] = useState("");
  const [ePageAccess, setEPageAccess] = useState("");
  const [pendingEdit, setPendingEdit] = useState<{
    action: string;
    payload: Record<string, unknown>;
    label: string;
    needsPassword: boolean;
  } | null>(null);

  function openEdit(a: WipeAccount) {
    setEditAcc(a);
    setEditPlayer(null);
    setEEmail(a.email || "");
    setEPass("");
    setEName(a.name);
    setEPageAccess(String(a.pageAccess));
    setErr("");
    setNote("");
  }

  // BEGIN CHANGE: item 5 (2026) - editor de dados do player (salvar/reset/group/nome)
  const [editPlayer, setEditPlayer] = useState<WipePlayer | null>(null);
  const [peName, setPeName] = useState("");
  const [peSalvar, setPeSalvar] = useState("");
  const [peReset, setPeReset] = useState("");
  const [peGroup, setPeGroup] = useState("");

  function openEditPlayer(p: WipePlayer) {
    setEditPlayer(p);
    setEditAcc(null);
    setPeName(p.name);
    setPeSalvar(String(p.salvar));
    setPeReset(String(p.reset));
    setPeGroup(String(p.groupId));
    setErr("");
    setNote("");
  }
  // END CHANGE

  async function runEdit(body: Record<string, unknown>) {
    setBusy(true);
    setErr("");
    setNote("");
    try {
      const r = await fetch(apiUrl("admin-panel.php"), {
        method: "POST",
        headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}` },
        body: JSON.stringify(body),
      });
      const json = await r.json().catch(() => ({}));
      if (!r.ok) throw new Error(json.error === "admin_password_required" ? "Senha de admin obrigatoria ou incorreta." : (json.error || "Falha na acao."));
      setNote(json.note || "OK");
      // BEGIN CHANGE: recarrega a aba ativa (players ou accounts)
      if (tab === "players") await loadPlayers(pApplied, pPage);
      else await loadAccounts(aApplied, aPage);
      // END CHANGE
    } catch (e) {
      setErr(e instanceof Error ? e.message : "Falha na acao.");
    } finally {
      setBusy(false);
    }
  }
  // END CHANGE

  const selectedPlayerIds = useMemo(
    () => Object.keys(pSelected).filter((k) => pSelected[Number(k)]).map(Number),
    [pSelected],
  );
  const selectedPlayerAccountIds = useMemo(() => {
    const set: Record<number, boolean> = {};
    players.forEach((p) => {
      if (pSelected[p.id]) set[p.accountId] = true;
    });
    return Object.keys(set).map(Number);
  }, [players, pSelected]);
  const selectedAccountIds = useMemo(
    () => Object.keys(aSelected).filter((k) => aSelected[Number(k)]).map(Number),
    [aSelected],
  );

  const loadPlayers = useCallback(
    async (f: PlayerFilters, pg: number) => {
      setBusy(true);
      setErr("");
      try {
        const r = await fetch(apiUrl(`admin-panel.php?${qsPlayer(f, pg, pageSize)}`), {
          headers: { Authorization: `Bearer ${token}` },
        });
        const json = await r.json().catch(() => ({}));
        if (!r.ok) throw new Error(json.error || "fail");
        const data = json.data || {};
        setPlayers((data.players || []) as WipePlayer[]);
        setPTotal(Number(data.total || 0));
        setPPages(Number(data.pages || 0));
        setPPage(Number(data.page || pg));
      } catch (e) {
        setErr(e instanceof Error ? e.message : "Falha ao carregar players.");
      } finally {
        setBusy(false);
      }
    },
    [pageSize, token],
  );

  const loadAccounts = useCallback(
    async (f: AccountFilters, pg: number) => {
      setBusy(true);
      setErr("");
      try {
        const r = await fetch(apiUrl(`admin-panel.php?${qsAccount(f, pg, pageSize)}`), {
          headers: { Authorization: `Bearer ${token}` },
        });
        const json = await r.json().catch(() => ({}));
        if (!r.ok) throw new Error(json.error || "fail");
        const data = json.data || {};
        setAccounts((data.accounts || []) as WipeAccount[]);
        setATotal(Number(data.total || 0));
        setAPages(Number(data.pages || 0));
        setAPage(Number(data.page || pg));
      } catch (e) {
        setErr(e instanceof Error ? e.message : "Falha ao carregar accounts.");
      } finally {
        setBusy(false);
      }
    },
    [pageSize, token],
  );

  useEffect(() => {
    if (!canUse) return;
    if (tab === "players") loadPlayers(pApplied, 1);
    else loadAccounts(aApplied, 1);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [canUse, tab, pApplied, aApplied, loadPlayers, loadAccounts]);

  async function runAction(body: Record<string, unknown>) {
    setBusy(true);
    setErr("");
    setNote("");
    setLastResult(null);
    try {
      const r = await fetch(apiUrl("admin-panel.php"), {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          Authorization: `Bearer ${token}`,
        },
        body: JSON.stringify(body),
      });
      const json = await r.json().catch(() => ({}));
      if (!r.ok) throw new Error(json.error || "Falha na acao.");
      setNote(json.note || "OK");
      setLastResult(json.result || null);
      setPSelected({});
      setASelected({});
      if (tab === "players") await loadPlayers(pApplied, pPage);
      else await loadAccounts(aApplied, aPage);
    } catch (e) {
      setErr(e instanceof Error ? e.message : "Falha na acao.");
    } finally {
      setBusy(false);
      setPending(null);
    }
  }

  if (!canUse) {
    return (
      <p className="rounded-lg border border-border bg-panel px-4 py-3 text-sm text-muted">
        Acesso restrito (page_access &gt;= 6). Exclusao em massa e zona critica.
      </p>
    );
  }

  return (
    <div className="space-y-4">
      <div>
        <h2 className="text-xl font-semibold">Wipe / Reset</h2>
        <p className="mt-1 text-sm text-muted">
          Players: exclusao destrutiva (contas preservadas). Accounts: devolver premium_points
          com base em backup_points (backup permanece intacto).
        </p>
      </div>

      <div className="flex gap-2">
        <button
          type="button"
          className={`rounded-md px-3 py-1.5 text-sm ${
            tab === "players" ? "bg-brand text-background" : "border border-border"
          }`}
          onClick={() => {
            setTab("players");
            setErr("");
            setNote("");
          }}
        >
          Players
        </button>
        <button
          type="button"
          className={`rounded-md px-3 py-1.5 text-sm ${
            tab === "accounts" ? "bg-brand text-background" : "border border-border"
          }`}
          onClick={() => {
            setTab("accounts");
            setErr("");
            setNote("");
          }}
        >
          Accounts
        </button>
      </div>

      {err && <p className="text-sm text-red-400">{err}</p>}
      {note && <p className="text-sm text-brand">{note}</p>}

      {tab === "players" && (
        <>
          <form
            className="grid gap-2 rounded-xl border border-border bg-panel p-4 sm:grid-cols-2 lg:grid-cols-4"
            onSubmit={(e) => {
              e.preventDefault();
              setPApplied({ ...pFilters });
              setPPage(1);
              setPSelected({});
            }}
          >
            {(
              [
                ["name", "Nome player"],
                ["account", "Conta"],
                ["salvar", "salvar (=)"],
                ["groupId", "group_id (=)"],
                ["pageAccess", "page_access (=)"],
                ["levelMin", "level min"],
                ["levelMax", "level max"],
                ["resetMin", "reset min"],
                ["resetMax", "reset max"],
                ["premiumMin", "premium_points min"],
                ["backupMin", "backup_points min"],
                ["guildPointsMin", "guild_points min"],
              ] as [keyof PlayerFilters, string][]
            ).map(([k, ph]) => (
              <input
                key={k}
                className="rounded-md border border-border bg-background px-3 py-2 text-sm"
                placeholder={ph}
                value={pFilters[k]}
                onChange={(e) => setPFilters((prev) => ({ ...prev, [k]: e.target.value }))}
              />
            ))}
            <select
              className="rounded-md border border-border bg-background px-3 py-2 text-sm"
              value={pFilters.online}
              onChange={(e) => setPFilters((prev) => ({ ...prev, online: e.target.value }))}
            >
              <option value="">online: todos</option>
              <option value="0">somente offline</option>
              <option value="1">somente online</option>
            </select>
            <select
              className="rounded-md border border-border bg-background px-3 py-2 text-sm"
              value={pFilters.deleted}
              onChange={(e) => setPFilters((prev) => ({ ...prev, deleted: e.target.value }))}
            >
              <option value="0">deleted = 0</option>
              <option value="1">deleted = 1</option>
              <option value="">deleted: todos</option>
            </select>
            <div className="flex flex-wrap gap-2 sm:col-span-2 lg:col-span-4">
              <button
                type="submit"
                disabled={busy}
                className="rounded-md bg-brand px-4 py-2 text-sm text-background disabled:opacity-50"
              >
                Filtrar
              </button>
              <button
                type="button"
                className="rounded-md border border-border px-3 py-2 text-sm"
                onClick={() => {
                  setPFilters(emptyPlayerFilters);
                  setPApplied(emptyPlayerFilters);
                  setPSelected({});
                }}
              >
                Limpar filtros
              </button>
              <span className="self-center text-xs text-muted">
                {pTotal} player(s) - pagina {pPage}/{Math.max(pPages, 1)}
              </span>
            </div>
          </form>

          <div className="flex flex-wrap gap-2">
            <button
              type="button"
              className="rounded-md border border-border px-3 py-1.5 text-sm"
              onClick={() =>
                setPSelected((prev) => {
                  const next = { ...prev };
                  players.forEach((p) => {
                    next[p.id] = true;
                  });
                  return next;
                })
              }
            >
              Marcar pagina
            </button>
            <button
              type="button"
              className="rounded-md border border-border px-3 py-1.5 text-sm"
              onClick={() => setPSelected({})}
            >
              Limpar selecao ({selectedPlayerIds.length})
            </button>
            <button
              type="button"
              disabled={busy || selectedPlayerIds.length === 0}
              className="rounded-md border border-red-500/50 px-3 py-1.5 text-sm text-red-400 disabled:opacity-50"
              onClick={() => setPending({ kind: "delete_selected" })}
            >
              Excluir selecionados
            </button>
            <button
              type="button"
              disabled={busy}
              className="rounded-md border border-red-500/50 px-3 py-1.5 text-sm text-red-400 disabled:opacity-50"
              onClick={() => setPending({ kind: "delete_except_keep" })}
            >
              Excluir filtrados EXCETO selecionados
            </button>
            <button
              type="button"
              disabled={busy || selectedPlayerAccountIds.length === 0}
              className="rounded-md border border-border px-3 py-1.5 text-sm disabled:opacity-50"
              onClick={() => setPending({ kind: "zero_guild_selected" })}
            >
              Zerar guild_points (contas dos selecionados)
            </button>
            <button
              type="button"
              disabled={busy}
              className="rounded-md border border-border px-3 py-1.5 text-sm disabled:opacity-50"
              onClick={() => setPending({ kind: "zero_guild_all" })}
            >
              Zerar guild_points (TODAS)
            </button>
          </div>

          {/* BEGIN CHANGE: item 5 (2026) - editor de dados do player */}
          {editPlayer && (
            <div className="grid gap-3 rounded-xl border border-brand/40 bg-panel p-4">
              <div className="flex items-center justify-between">
                <h3 className="text-sm font-semibold">
                  Editar player: {editPlayer.name} (#{editPlayer.id})
                  {editPlayer.online ? <span className="ml-2 text-brand">ONLINE</span> : null}
                </h3>
                <button
                  type="button"
                  className="rounded border border-border px-2 py-1 text-xs"
                  onClick={() => setEditPlayer(null)}
                >
                  Fechar
                </button>
              </div>
              <div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-4">
                <div className="space-y-1">
                  <label className="text-xs text-muted">Nome (renomear)</label>
                  <input
                    className="w-full rounded border border-border bg-background px-2 py-1.5 text-sm"
                    value={peName}
                    onChange={(e) => setPeName(e.target.value)}
                  />
                  <button
                    type="button"
                    disabled={busy || editPlayer.online || peName.trim() === "" || peName === editPlayer.name}
                    className="rounded bg-brand px-3 py-1 text-xs text-background disabled:opacity-50"
                    onClick={() => runEdit({ action: "rename_player", playerId: editPlayer.id, newName: peName.trim() })}
                  >
                    Salvar nome
                  </button>
                </div>
                <div className="space-y-1">
                  <label className="text-xs text-muted">salvar (0-10)</label>
                  <input
                    className="w-full rounded border border-border bg-background px-2 py-1.5 text-sm"
                    value={peSalvar}
                    onChange={(e) => setPeSalvar(e.target.value)}
                  />
                  <button
                    type="button"
                    disabled={busy}
                    className="rounded bg-brand px-3 py-1 text-xs text-background disabled:opacity-50"
                    onClick={() => runEdit({ action: "set_salvar", playerId: editPlayer.id, salvar: Number(peSalvar) })}
                  >
                    Salvar salvar
                  </button>
                </div>
                <div className="space-y-1">
                  <label className="text-xs text-muted">reset</label>
                  <input
                    className="w-full rounded border border-border bg-background px-2 py-1.5 text-sm"
                    value={peReset}
                    onChange={(e) => setPeReset(e.target.value)}
                  />
                  <button
                    type="button"
                    disabled={busy}
                    className="rounded bg-brand px-3 py-1 text-xs text-background disabled:opacity-50"
                    onClick={() => runEdit({ action: "set_reset", playerId: editPlayer.id, reset: Number(peReset) })}
                  >
                    Salvar reset
                  </button>
                </div>
                <div className="space-y-1">
                  <label className="text-xs text-muted">group_id (1-7)</label>
                  <input
                    className="w-full rounded border border-border bg-background px-2 py-1.5 text-sm"
                    value={peGroup}
                    onChange={(e) => setPeGroup(e.target.value)}
                  />
                  <button
                    type="button"
                    disabled={busy}
                    className="rounded bg-brand px-3 py-1 text-xs text-background disabled:opacity-50"
                    onClick={() =>
                      setPendingEdit({
                        action: "set_player_group",
                        payload: { action: "set_player_group", playerId: editPlayer.id, groupId: Number(peGroup) },
                        label: `Definir group_id=${peGroup} no player ${editPlayer.name}`,
                        needsPassword: true,
                      })
                    }
                  >
                    Salvar group
                  </button>
                </div>
              </div>
              <p className="text-xs text-muted">
                salvar/reset/nome requerem page_access &gt;= 5. group_id requer page_access &gt;= 6 e sua senha de admin.
                Renomear exige o player offline. salvar: 0 = visivel; &gt; 0 = so online + /character; &gt; 1 = oculto de tudo no portal.
              </p>
            </div>
          )}
          {/* END CHANGE */}

          <div className="overflow-auto rounded-xl border border-border">
            <table className="min-w-full text-left text-xs">
              <thead className="bg-panel text-muted">
                <tr>
                  <th className="px-2 py-2"> </th>
                  <th className="px-2 py-2">Player</th>
                  <th className="px-2 py-2">Conta</th>
                  <th className="px-2 py-2">Lv</th>
                  <th className="px-2 py-2">EXP</th>
                  <th className="px-2 py-2">ML</th>
                  <th className="px-2 py-2">Skills</th>
                  <th className="px-2 py-2">PP</th>
                  <th className="px-2 py-2">BP</th>
                  <th className="px-2 py-2">GP</th>
                  <th className="px-2 py-2">salvar</th>
                  <th className="px-2 py-2">group</th>
                  <th className="px-2 py-2">RR</th>
                  <th className="px-2 py-2">flags</th>
                  <th className="px-2 py-2">lastlogin</th>
                  {/* BEGIN CHANGE: item 5 (2026) - coluna editar player */}
                  <th className="px-2 py-2">Editar</th>
                  {/* END CHANGE */}
                </tr>
              </thead>
              <tbody>
                {players.map((p) => {
                  const sk = p.skills;
                  return (
                    <tr key={p.id} className="border-t border-border/60 hover:bg-panel/60">
                      <td className="px-2 py-1">
                        <input
                          type="checkbox"
                          checked={!!pSelected[p.id]}
                          onChange={(e) =>
                            setPSelected((prev) => ({ ...prev, [p.id]: e.target.checked }))
                          }
                        />
                      </td>
                      <td className="px-2 py-1 font-medium">{p.name}</td>
                      <td className="px-2 py-1">
                        {p.accountName}
                        <span className="text-muted"> #{p.accountId}</span>
                      </td>
                      <td className="px-2 py-1 tabular-nums">{p.level}</td>
                      <td className="px-2 py-1 tabular-nums">{p.experience}</td>
                      <td className="px-2 py-1 tabular-nums">{p.magic}</td>
                      <td className="px-2 py-1 tabular-nums text-[10px] text-muted">
                        F{sk.fist} C{sk.club} S{sk.sword} A{sk.axe} D{sk.distance} Sh{sk.shielding}{" "}
                        Fi{sk.fishing}
                      </td>
                      <td className="px-2 py-1 tabular-nums">{p.premiumPoints}</td>
                      <td className="px-2 py-1 tabular-nums">{p.backupPoints}</td>
                      <td className="px-2 py-1 tabular-nums">{p.guildPoints}</td>
                      <td className="px-2 py-1 tabular-nums">{p.salvar}</td>
                      <td className="px-2 py-1 tabular-nums">{p.groupId}</td>
                      <td className="px-2 py-1 tabular-nums">{p.reset}</td>
                      <td className="px-2 py-1">
                        {p.online ? <span className="text-brand">ON</span> : <span className="text-muted">off</span>}
                        {p.deleted ? " DEL" : ""}
                        {p.pageAccess > 0 ? ` ACL${p.pageAccess}` : ""}
                      </td>
                      <td className="px-2 py-1 whitespace-nowrap">{fmtTs(p.lastlogin)}</td>
                      {/* BEGIN CHANGE: item 5 (2026) - abrir editor do player */}
                      <td className="px-2 py-1">
                        <button
                          type="button"
                          className="rounded border border-border px-2 py-1 text-xs hover:border-brand"
                          onClick={() => openEditPlayer(p)}
                        >
                          Editar
                        </button>
                      </td>
                      {/* END CHANGE */}
                    </tr>
                  );
                })}
                {players.length === 0 && !busy && (
                  <tr>
                    <td colSpan={16} className="px-3 py-6 text-center text-muted">
                      Nenhum player com esses filtros.
                    </td>
                  </tr>
                )}
              </tbody>
            </table>
          </div>

          <div className="flex flex-wrap items-center gap-2">
            <button
              type="button"
              disabled={busy || pPage <= 1}
              className="rounded-md border border-border px-3 py-1.5 text-sm disabled:opacity-50"
              onClick={() => {
                const next = Math.max(1, pPage - 1);
                setPPage(next);
                loadPlayers(pApplied, next);
              }}
            >
              Anterior
            </button>
            <button
              type="button"
              disabled={busy || pPage >= pPages}
              className="rounded-md border border-border px-3 py-1.5 text-sm disabled:opacity-50"
              onClick={() => {
                const next = pPage + 1;
                setPPage(next);
                loadPlayers(pApplied, next);
              }}
            >
              Proxima
            </button>
            {busy && <span className="text-sm text-muted">Processando...</span>}
          </div>
        </>
      )}

      {tab === "accounts" && (
        <>
          <form
            className="grid gap-2 rounded-xl border border-border bg-panel p-4 sm:grid-cols-2 lg:grid-cols-4"
            onSubmit={(e) => {
              e.preventDefault();
              setAApplied({ ...aFilters });
              setAPage(1);
              setASelected({});
            }}
          >
            <input
              className="rounded-md border border-border bg-background px-3 py-2 text-sm"
              placeholder="Nome conta"
              value={aFilters.account}
              onChange={(e) => setAFilters((prev) => ({ ...prev, account: e.target.value }))}
            />
            <input
              className="rounded-md border border-border bg-background px-3 py-2 text-sm"
              placeholder="E-mail"
              value={aFilters.email}
              onChange={(e) => setAFilters((prev) => ({ ...prev, email: e.target.value }))}
            />
            <input
              className="rounded-md border border-border bg-background px-3 py-2 text-sm"
              placeholder="page_access (=)"
              value={aFilters.pageAccess}
              onChange={(e) => setAFilters((prev) => ({ ...prev, pageAccess: e.target.value }))}
            />
            <select
              className="rounded-md border border-border bg-background px-3 py-2 text-sm"
              value={aFilters.blocked}
              onChange={(e) => setAFilters((prev) => ({ ...prev, blocked: e.target.value }))}
            >
              <option value="">blocked: todos</option>
              <option value="0">nao bloqueadas</option>
              <option value="1">bloqueadas</option>
            </select>
            <input
              className="rounded-md border border-border bg-background px-3 py-2 text-sm"
              placeholder="premium_points min"
              value={aFilters.premiumMin}
              onChange={(e) => setAFilters((prev) => ({ ...prev, premiumMin: e.target.value }))}
            />
            <input
              className="rounded-md border border-border bg-background px-3 py-2 text-sm"
              placeholder="backup_points min"
              value={aFilters.backupMin}
              onChange={(e) => setAFilters((prev) => ({ ...prev, backupMin: e.target.value }))}
            />
            <input
              className="rounded-md border border-border bg-background px-3 py-2 text-sm"
              placeholder="guild_points min"
              value={aFilters.guildPointsMin}
              onChange={(e) => setAFilters((prev) => ({ ...prev, guildPointsMin: e.target.value }))}
            />
            <select
              className="rounded-md border border-border bg-background px-3 py-2 text-sm"
              value={aFilters.hasPlayers}
              onChange={(e) => setAFilters((prev) => ({ ...prev, hasPlayers: e.target.value }))}
            >
              <option value="">chars: todos</option>
              <option value="1">com chars</option>
              <option value="0">sem chars</option>
            </select>
            <select
              className="rounded-md border border-border bg-background px-3 py-2 text-sm"
              value={aFilters.ppDiffersBackup}
              onChange={(e) =>
                setAFilters((prev) => ({ ...prev, ppDiffersBackup: e.target.value }))
              }
            >
              <option value="">PP vs BP: todos</option>
              <option value="1">PP diferente de BP</option>
              <option value="0">PP igual a BP</option>
            </select>
            <div className="flex flex-wrap gap-2 sm:col-span-2 lg:col-span-4">
              <button
                type="submit"
                disabled={busy}
                className="rounded-md bg-brand px-4 py-2 text-sm text-background disabled:opacity-50"
              >
                Filtrar
              </button>
              <button
                type="button"
                className="rounded-md border border-border px-3 py-2 text-sm"
                onClick={() => {
                  setAFilters(emptyAccountFilters);
                  setAApplied(emptyAccountFilters);
                  setASelected({});
                }}
              >
                Limpar filtros
              </button>
              <span className="self-center text-xs text-muted">
                {aTotal} conta(s) - pagina {aPage}/{Math.max(aPages, 1)}
              </span>
            </div>
          </form>

          <div className="flex flex-wrap gap-2">
            <button
              type="button"
              className="rounded-md border border-border px-3 py-1.5 text-sm"
              onClick={() =>
                setASelected((prev) => {
                  const next = { ...prev };
                  accounts.forEach((a) => {
                    next[a.id] = true;
                  });
                  return next;
                })
              }
            >
              Marcar pagina
            </button>
            <button
              type="button"
              className="rounded-md border border-border px-3 py-1.5 text-sm"
              onClick={() => setASelected({})}
            >
              Limpar selecao ({selectedAccountIds.length})
            </button>
            <button
              type="button"
              disabled={busy || selectedAccountIds.length === 0}
              className="rounded-md border border-brand/50 px-3 py-1.5 text-sm text-brand disabled:opacity-50"
              onClick={() => setPending({ kind: "restore_pp_selected" })}
            >
              Devolver PP = BP (selecionadas)
            </button>
            <button
              type="button"
              disabled={busy}
              className="rounded-md border border-brand/50 px-3 py-1.5 text-sm text-brand disabled:opacity-50"
              onClick={() => setPending({ kind: "restore_pp_filtered" })}
            >
              Devolver PP = BP (filtradas)
            </button>
            <button
              type="button"
              disabled={busy}
              className="rounded-md border border-brand/50 px-3 py-1.5 text-sm text-brand disabled:opacity-50"
              onClick={() => setPending({ kind: "restore_pp_all_backup" })}
            >
              Devolver PP = BP (todas com BP &gt; 0)
            </button>
            <button
              type="button"
              disabled={busy || selectedAccountIds.length === 0}
              className="rounded-md border border-border px-3 py-1.5 text-sm disabled:opacity-50"
              onClick={() => setPending({ kind: "zero_guild_selected" })}
            >
              Zerar guild_points (selecionadas)
            </button>
          </div>

          {/* BEGIN CHANGE: item 11 - editor de dados da conta */}
          {editAcc && (
            <div className="grid gap-3 rounded-xl border border-brand/40 bg-panel p-4">
              <div className="flex items-center justify-between">
                <h3 className="text-sm font-semibold">
                  Editar conta: {editAcc.name} (#{editAcc.id})
                </h3>
                <button
                  type="button"
                  className="rounded border border-border px-2 py-1 text-xs"
                  onClick={() => setEditAcc(null)}
                >
                  Fechar
                </button>
              </div>
              <div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-4">
                <div className="space-y-1">
                  <label className="text-xs text-muted">E-mail</label>
                  <input
                    className="w-full rounded border border-border bg-background px-2 py-1.5 text-sm"
                    value={eEmail}
                    onChange={(e) => setEEmail(e.target.value)}
                  />
                  <button
                    type="button"
                    disabled={busy}
                    className="rounded bg-brand px-3 py-1 text-xs text-background disabled:opacity-50"
                    onClick={() => runEdit({ action: "set_email", accountId: editAcc.id, email: eEmail })}
                  >
                    Salvar e-mail
                  </button>
                </div>
                <div className="space-y-1">
                  <label className="text-xs text-muted">Nova senha</label>
                  <input
                    className="w-full rounded border border-border bg-background px-2 py-1.5 text-sm"
                    value={ePass}
                    onChange={(e) => setEPass(e.target.value)}
                    placeholder="1-20 alfanumerico"
                  />
                  <button
                    type="button"
                    disabled={busy || ePass.trim() === ""}
                    className="rounded bg-brand px-3 py-1 text-xs text-background disabled:opacity-50"
                    onClick={() =>
                      setPendingEdit({
                        action: "set_password",
                        payload: { action: "set_password", accountId: editAcc.id, password: ePass },
                        label: `Definir nova senha da conta ${editAcc.name}`,
                        needsPassword: true,
                      })
                    }
                  >
                    Salvar senha
                  </button>
                </div>
                <div className="space-y-1">
                  <label className="text-xs text-muted">Nome da conta</label>
                  <input
                    className="w-full rounded border border-border bg-background px-2 py-1.5 text-sm"
                    value={eName}
                    onChange={(e) => setEName(e.target.value)}
                  />
                  <button
                    type="button"
                    disabled={busy}
                    className="rounded bg-brand px-3 py-1 text-xs text-background disabled:opacity-50"
                    onClick={() =>
                      setPendingEdit({
                        action: "set_account_name",
                        payload: { action: "set_account_name", accountId: editAcc.id, accountName: eName },
                        label: `Renomear conta #${editAcc.id} para "${eName}"`,
                        needsPassword: true,
                      })
                    }
                  >
                    Salvar nome
                  </button>
                </div>
                <div className="space-y-1">
                  <label className="text-xs text-muted">page_access</label>
                  <input
                    className="w-full rounded border border-border bg-background px-2 py-1.5 text-sm"
                    value={ePageAccess}
                    onChange={(e) => setEPageAccess(e.target.value)}
                  />
                  <button
                    type="button"
                    disabled={busy}
                    className="rounded bg-brand px-3 py-1 text-xs text-background disabled:opacity-50"
                    onClick={() =>
                      setPendingEdit({
                        action: "set_page_access",
                        payload: { action: "set_page_access", accountId: editAcc.id, pageAccess: Number(ePageAccess) },
                        label: `Definir page_access=${ePageAccess} na conta ${editAcc.name}`,
                        needsPassword: true,
                      })
                    }
                  >
                    Salvar ACL
                  </button>
                </div>
              </div>
              <p className="text-xs text-muted">
                E-mail requer page_access &gt;= 5. Senha, nome e ACL requerem page_access &gt;= 6 e sua senha de admin.
              </p>
            </div>
          )}
          {/* END CHANGE */}

          <div className="overflow-auto rounded-xl border border-border">
            <table className="min-w-full text-left text-xs">
              <thead className="bg-panel text-muted">
                <tr>
                  <th className="px-2 py-2"> </th>
                  <th className="px-2 py-2">ID</th>
                  <th className="px-2 py-2">Conta</th>
                  <th className="px-2 py-2">E-mail</th>
                  <th className="px-2 py-2">PP</th>
                  <th className="px-2 py-2">BP</th>
                  <th className="px-2 py-2">Diff</th>
                  <th className="px-2 py-2">GP</th>
                  <th className="px-2 py-2">Chars</th>
                  <th className="px-2 py-2">ACL</th>
                  <th className="px-2 py-2">flags</th>
                  <th className="px-2 py-2">created</th>
                  {/* BEGIN CHANGE: item 11 - coluna de edicao */}
                  <th className="px-2 py-2">Editar</th>
                  {/* END CHANGE */}
                </tr>
              </thead>
              <tbody>
                {accounts.map((a) => (
                  <tr key={a.id} className="border-t border-border/60 hover:bg-panel/60">
                    <td className="px-2 py-1">
                      <input
                        type="checkbox"
                        checked={!!aSelected[a.id]}
                        onChange={(e) =>
                          setASelected((prev) => ({ ...prev, [a.id]: e.target.checked }))
                        }
                      />
                    </td>
                    <td className="px-2 py-1 tabular-nums">{a.id}</td>
                    <td className="px-2 py-1 font-medium">{a.name}</td>
                    <td className="px-2 py-1 text-muted">{a.email || "-"}</td>
                    <td className="px-2 py-1 tabular-nums">{a.premiumPoints}</td>
                    <td className="px-2 py-1 tabular-nums">{a.backupPoints}</td>
                    <td className="px-2 py-1 tabular-nums">
                      {a.ppDiffersBackup ? (
                        <span className="text-brand">
                          {a.backupPoints - a.premiumPoints > 0 ? "+" : ""}
                          {a.backupPoints - a.premiumPoints}
                        </span>
                      ) : (
                        <span className="text-muted">0</span>
                      )}
                    </td>
                    <td className="px-2 py-1 tabular-nums">{a.guildPoints}</td>
                    <td className="px-2 py-1 tabular-nums">
                      {a.playerCount}
                      {a.onlineCount > 0 ? (
                        <span className="text-brand"> ({a.onlineCount} on)</span>
                      ) : null}
                    </td>
                    <td className="px-2 py-1 tabular-nums">{a.pageAccess}</td>
                    <td className="px-2 py-1">{a.blocked ? "blocked" : "-"}</td>
                    <td className="px-2 py-1 whitespace-nowrap">{fmtTs(a.created)}</td>
                    {/* BEGIN CHANGE: item 11 - abrir editor da conta */}
                    <td className="px-2 py-1">
                      <button
                        type="button"
                        className="rounded border border-border px-2 py-1 text-xs hover:border-brand"
                        onClick={() => openEdit(a)}
                      >
                        Editar
                      </button>
                    </td>
                    {/* END CHANGE */}
                  </tr>
                ))}
                {accounts.length === 0 && !busy && (
                  <tr>
                    <td colSpan={13} className="px-3 py-6 text-center text-muted">
                      Nenhuma conta com esses filtros.
                    </td>
                  </tr>
                )}
              </tbody>
            </table>
          </div>

          <div className="flex flex-wrap items-center gap-2">
            <button
              type="button"
              disabled={busy || aPage <= 1}
              className="rounded-md border border-border px-3 py-1.5 text-sm disabled:opacity-50"
              onClick={() => {
                const next = Math.max(1, aPage - 1);
                setAPage(next);
                loadAccounts(aApplied, next);
              }}
            >
              Anterior
            </button>
            <button
              type="button"
              disabled={busy || aPage >= aPages}
              className="rounded-md border border-border px-3 py-1.5 text-sm disabled:opacity-50"
              onClick={() => {
                const next = aPage + 1;
                setAPage(next);
                loadAccounts(aApplied, next);
              }}
            >
              Proxima
            </button>
            {busy && <span className="text-sm text-muted">Processando...</span>}
          </div>
        </>
      )}

      {lastResult != null && (
        <pre className="max-h-64 overflow-auto rounded-xl border border-border bg-panel p-3 text-[11px]">
          {JSON.stringify(lastResult, null, 2)}
        </pre>
      )}

      <AdminConfirmModal
        open={!!pending}
        title={
          pending?.kind === "zero_guild_all"
            ? "Zerar guild_points de TODAS as contas"
            : pending?.kind === "zero_guild_selected"
              ? `Zerar guild_points de ${tab === "accounts" ? selectedAccountIds.length : selectedPlayerAccountIds.length} conta(s)`
              : pending?.kind === "delete_except_keep"
                ? "Excluir TODOS os filtrados EXCETO os selecionados"
                : pending?.kind === "restore_pp_selected"
                  ? `Devolver PP = BP em ${selectedAccountIds.length} conta(s)`
                  : pending?.kind === "restore_pp_filtered"
                    ? "Devolver PP = BP em todas as contas filtradas"
                    : pending?.kind === "restore_pp_all_backup"
                      ? "Devolver PP = BP em todas as contas com BP > 0"
                      : `Excluir ${selectedPlayerIds.length} player(s) selecionado(s)`
        }
        hint={
          pending?.kind?.startsWith("restore_pp")
            ? "Define premium_points = backup_points. backup_points nao muda. Digite DELETE e sua senha."
            : pending?.kind?.startsWith("zero_guild")
              ? "Isso nao apaga accounts nem premium/backup points. Digite DELETE e sua senha."
              : "Irreversivel: itens, depot, houses, quests e rastros do personagem. Accounts e pontos comprados ficam. Players online sao pulados. Digite DELETE e sua senha."
        }
        requirePassword
        requireDeleteWord
        confirmLabel="Confirmar"
        cancelLabel="Cancelar"
        passwordLabel="Sua senha de admin"
        onCancel={() => setPending(null)}
        onConfirm={({ adminPassword, confirm }) => {
          if (!pending) return;
          if (pending.kind === "delete_selected") {
            runAction({
              action: "mass_delete_players",
              mode: "selected",
              playerIds: selectedPlayerIds,
              confirm,
              adminPassword,
              limit: 200,
            });
            return;
          }
          if (pending.kind === "delete_except_keep") {
            runAction({
              action: "mass_delete_players",
              mode: "except_keep",
              keepPlayerIds: selectedPlayerIds,
              filters: numKeysPayload(pApplied, [
                "salvar",
                "groupId",
                "pageAccess",
                "levelMin",
                "levelMax",
                "resetMin",
                "resetMax",
                "online",
                "deleted",
                "premiumMin",
                "backupMin",
                "guildPointsMin",
              ]),
              confirm,
              adminPassword,
              limit: 200,
            });
            return;
          }
          if (pending.kind === "zero_guild_all") {
            runAction({
              action: "zero_guild_points",
              scope: "all",
              confirm,
              adminPassword,
            });
            return;
          }
          if (pending.kind === "zero_guild_selected") {
            runAction({
              action: "zero_guild_points",
              scope: "selected",
              accountIds: tab === "accounts" ? selectedAccountIds : selectedPlayerAccountIds,
              confirm,
              adminPassword,
            });
            return;
          }
          if (pending.kind === "restore_pp_selected") {
            runAction({
              action: "restore_premium_from_backup",
              scope: "selected",
              accountIds: selectedAccountIds,
              confirm,
              adminPassword,
            });
            return;
          }
          if (pending.kind === "restore_pp_filtered") {
            runAction({
              action: "restore_premium_from_backup",
              scope: "filtered",
              filters: numKeysPayload(aApplied, [
                "pageAccess",
                "blocked",
                "premiumMin",
                "backupMin",
                "guildPointsMin",
                "hasPlayers",
                "ppDiffersBackup",
              ]),
              confirm,
              adminPassword,
            });
            return;
          }
          runAction({
            action: "restore_premium_from_backup",
            scope: "all_with_backup",
            confirm,
            adminPassword,
          });
        }}
      />

      {/* BEGIN CHANGE: item 11 - confirmacao (so senha) para editar conta */}
      <AdminConfirmModal
        open={!!pendingEdit}
        title={pendingEdit?.label || ""}
        hint="Confirme com sua senha de admin."
        requirePassword
        confirmLabel="Confirmar"
        cancelLabel="Cancelar"
        passwordLabel="Sua senha de admin"
        onCancel={() => setPendingEdit(null)}
        onConfirm={({ adminPassword }) => {
          const p = pendingEdit;
          setPendingEdit(null);
          if (p) runEdit({ ...p.payload, adminPassword });
        }}
      />
      {/* END CHANGE */}
    </div>
  );
}
// END CHANGE
