// BEGIN CHANGE: ficha de guild + painel manage (logo, ranks, invites, kick)
"use client";

import { useCallback, useEffect, useState, FormEvent } from "react";
import Link from "next/link";
import { useI18n } from "@/i18n/LanguageProvider";
import { useAuth } from "@/auth/AuthProvider";
import { Navbar } from "@/components/Navbar";
import { Footer } from "@/components/Footer";
import { PlayerName } from "@/components/PlayerName";
import { GuildWarsList, type WarRow } from "@/components/GuildWarsList";
import { apiUrl, guildLogoUrl, type Look } from "@/lib/api";

type Member = {
  playerId: number;
  name: string;
  guildNick: string;
  level: number;
  vocation: string;
  online: boolean;
  rankId: number;
  rankLevel: number;
  isOwner: boolean;
  look: Look;
};
type Rank = { id: number; name: string; level: number; members: Member[] };
type RankOpt = { id: number; name: string; level: number };
type Perms = {
  isOwner: boolean;
  level: number;
  canManage: boolean;
  canInvite: boolean;
  canKick: boolean;
  canChangeRank: boolean;
  isMember: boolean;
  isAdmin?: boolean;
  myInvited: string[];
  myMembers: string[];
};
type Stats = {
  members: number;
  online: number;
  totalLevel: number;
  avgLevel: number;
  lowest: string | null;
  highest: string | null;
  invites: number;
};
type Guild = {
  id: number;
  name: string;
  owner: string;
  ownerLook: Look | null;
  motd: string;
  description: string;
  logo: string;
  created: number;
  castle: boolean;
  favela: boolean;
  membersCount: number;
  ranks: Rank[];
  allRanks: RankOpt[];
  invites: { name: string }[];
  stats: Stats;
  wars?: WarRow[];
  permissions: Perms;
  canManage: boolean;
};

export default function GuildPage() {
  const { t } = useI18n();
  const { ready, token } = useAuth();
  const [data, setData] = useState<Guild | null>(null);
  const [status, setStatus] = useState<"loading" | "ok" | "error" | "notfound">("loading");
  const [msg, setMsg] = useState("");
  const [err, setErr] = useState("");
  const [busy, setBusy] = useState(false);

  // Form state (owner)
  const [description, setDescription] = useState("");
  const [motd, setMotd] = useState("");
  const [rankEdits, setRankEdits] = useState<RankOpt[]>([]);
  const [newRankName, setNewRankName] = useState("");
  const [inviteName, setInviteName] = useState("");
  const [nickEdits, setNickEdits] = useState<Record<string, string>>({});
  const [newRankLevel, setNewRankLevel] = useState(1);
  const [passTo, setPassTo] = useState("");
  const [deleteConfirm, setDeleteConfirm] = useState("");

  const authHeaders = useCallback(
    (json = true): HeadersInit => {
      const h: Record<string, string> = {};
      if (json) h["Content-Type"] = "application/json";
      if (token) h.Authorization = `Bearer ${token}`;
      return h;
    },
    [token]
  );

  const load = useCallback(() => {
    const q = new URLSearchParams(window.location.search);
    const id = q.get("id");
    const name = q.get("name");
    const path = id
      ? `guild.php?id=${encodeURIComponent(id)}`
      : name
        ? `guild.php?name=${encodeURIComponent(name)}`
        : "";
    if (!path) {
      setStatus("notfound");
      return;
    }
    setStatus("loading");
    fetch(apiUrl(path), { headers: authHeaders(false) })
      .then((r) => {
        if (r.status === 404) {
          setStatus("notfound");
          return null;
        }
        if (!r.ok) throw new Error("http " + r.status);
        return r.json();
      })
      .then((json) => {
        if (!json) return;
        const g = json.data as Guild;
        setData(g);
        setDescription(g.description || "");
        setMotd(g.motd || "");
        setRankEdits((g.allRanks || []).map((r) => ({ ...r })));
        const nicks: Record<string, string> = {};
        for (const rank of g.ranks || []) {
          for (const m of rank.members || []) {
            nicks[m.name] = m.guildNick || "";
          }
        }
        setNickEdits(nicks);
        setStatus("ok");
      })
      .catch(() => setStatus("error"));
  }, [authHeaders]);

  useEffect(() => {
    if (!ready) return;
    load();
  }, [ready, load]);

  async function manage(body: Record<string, unknown>) {
    setBusy(true);
    setMsg("");
    setErr("");
    try {
      const r = await fetch(apiUrl("guild-manage.php"), {
        method: "POST",
        headers: authHeaders(true),
        body: JSON.stringify(body),
      });
      const j = await r.json().catch(() => ({}));
      if (!r.ok) {
        setErr(t.guilds.actionFailed);
        return false;
      }
      if (j && j.ok) {
        setMsg(t.guilds.saved);
        if (!j.deleted) load();
        return true;
      }
      setErr(t.guilds.actionFailed);
      return false;
    } catch {
      setErr(t.guilds.actionFailed);
      return false;
    } finally {
      setBusy(false);
    }
  }

  async function saveProfile(e: FormEvent) {
    e.preventDefault();
    if (!data || !token) return;
    setBusy(true);
    setMsg("");
    setErr("");
    try {
      const r = await fetch(apiUrl("guild-update.php"), {
        method: "POST",
        headers: authHeaders(true),
        body: JSON.stringify({ id: data.id, description, motd }),
      });
      if (!r.ok) {
        setErr(t.guilds.actionFailed);
        return;
      }
      setMsg(t.guilds.saved);
      load();
    } catch {
      setErr(t.guilds.actionFailed);
    } finally {
      setBusy(false);
    }
  }

  async function uploadLogo(file: File | null) {
    if (!data || !token || !file) return;
    setBusy(true);
    setMsg("");
    setErr("");
    try {
      const fd = new FormData();
      fd.append("id", String(data.id));
      fd.append("logo", file);
      const r = await fetch(apiUrl("guild-logo.php"), {
        method: "POST",
        headers: { Authorization: `Bearer ${token}` },
        body: fd,
      });
      if (!r.ok) {
        setErr(t.guilds.actionFailed);
        return;
      }
      setMsg(t.guilds.saved);
      load();
    } catch {
      setErr(t.guilds.actionFailed);
    } finally {
      setBusy(false);
    }
  }

  const fmtDate = (epoch: number) =>
    epoch > 0
      ? new Date(epoch * 1000).toLocaleDateString(undefined, {
          year: "numeric",
          month: "long",
          day: "numeric",
        })
      : "-";

  const perms = data?.permissions;
  const myMembers = new Set(perms?.myMembers || []);
  const canEditNick = (name: string) => !!(perms?.isOwner || myMembers.has(name));
  const showManage = !!(perms && (perms.canManage || perms.canInvite || perms.myInvited?.length));

  return (
    <div className="flex min-h-screen flex-col">
      <Navbar />
      <main className="mx-auto w-full max-w-4xl flex-1 px-6 py-14">
        <Link href="/guilds" className="text-sm text-muted hover:text-brand">
          &larr; {t.guilds.back}
        </Link>

        {status === "loading" && <p className="mt-8 text-muted">{t.common.loading}</p>}
        {status === "error" && <p className="mt-8 text-muted">{t.common.error}</p>}
        {status === "notfound" && <p className="mt-8 text-muted">{t.common.empty}</p>}

        {status === "ok" && data && (
          <div className="mt-6 space-y-6">
            <div className="flex flex-col items-center gap-4 rounded-xl border border-border bg-panel p-6 sm:flex-row sm:items-start">
              {/* eslint-disable-next-line @next/next/no-img-element */}
              <img
                src={guildLogoUrl(data.logo)}
                alt={data.name}
                width={96}
                height={96}
                className="h-24 w-24 rounded object-contain"
                onError={(e) => {
                  (e.target as HTMLImageElement).src = guildLogoUrl("default_main_logo.gif");
                }}
              />
              <div className="flex-1 text-center sm:text-left">
                <div className="flex flex-wrap items-center justify-center gap-2 sm:justify-start">
                  <h1 className="text-3xl font-semibold tracking-tight">{data.name}</h1>
                  {data.castle && (
                    <span className="rounded bg-brand/15 px-2 py-0.5 text-xs text-brand">
                      {t.guilds.castle}
                    </span>
                  )}
                  {data.favela && (
                    <span className="rounded bg-brand/15 px-2 py-0.5 text-xs text-brand">
                      {t.guilds.favela}
                    </span>
                  )}
                </div>
                {data.description && (
                  <p className="mt-2 whitespace-pre-line text-sm text-muted">{data.description}</p>
                )}
                <div className="mt-3 space-y-1 text-sm">
                  <div className="flex flex-wrap items-center justify-center gap-2 sm:justify-start">
                    <span className="text-muted">{t.guilds.leader}:</span>
                    {data.owner !== "-" ? (
                      <PlayerName name={data.owner} look={data.ownerLook} size="inline" />
                    ) : (
                      <span>-</span>
                    )}
                  </div>
                  <div className="text-muted">
                    {t.guilds.founded}: {fmtDate(data.created)}
                  </div>
                  <div className="text-muted">
                    {t.guilds.members}: {data.membersCount}
                  </div>
                  {data.motd && (
                    <div className="text-muted">
                      {t.guilds.colMotd}: {data.motd}
                    </div>
                  )}
                </div>
              </div>
            </div>

            {(msg || err) && (
              <p className={`text-sm ${err ? "text-red-400" : "text-brand"}`}>{err || msg}</p>
            )}

            {showManage && (
              <div className="space-y-6 rounded-xl border border-border bg-panel p-6">
                <h2 className="text-lg font-semibold">{t.guilds.manage}</h2>

                {perms?.myInvited && perms.myInvited.length > 0 && (
                  <div className="space-y-2">
                    <h3 className="text-sm font-semibold">{t.guilds.acceptInvite}</h3>
                    <ul className="space-y-2">
                      {perms.myInvited.map((n) => (
                        <li key={n} className="flex items-center justify-between gap-3 text-sm">
                          <span>{n}</span>
                          <button
                            type="button"
                            disabled={busy}
                            className="rounded bg-brand px-3 py-1 text-xs font-medium text-background disabled:opacity-50"
                            onClick={() => manage({ action: "accept_invite", id: data.id, name: n })}
                          >
                            {t.guilds.acceptInvite}
                          </button>
                        </li>
                      ))}
                    </ul>
                  </div>
                )}

                {perms?.canManage && (
                  <>
                    <form onSubmit={saveProfile} className="space-y-4">
                      <div>
                        <label className="mb-1 block text-sm text-muted">{t.guilds.editDescription}</label>
                        <textarea
                          value={description}
                          onChange={(e) => setDescription(e.target.value)}
                          maxLength={1000}
                          rows={4}
                          className="w-full rounded-lg border border-border bg-background px-3 py-2 text-sm outline-none focus:border-brand/60"
                        />
                        <p className="mt-1 text-xs text-muted">{t.guilds.descLimit}</p>
                      </div>
                      <div>
                        <label className="mb-1 block text-sm text-muted">{t.guilds.editMotd}</label>
                        <input
                          value={motd}
                          onChange={(e) => setMotd(e.target.value)}
                          maxLength={150}
                          className="w-full rounded-lg border border-border bg-background px-3 py-2 text-sm outline-none focus:border-brand/60"
                        />
                        <p className="mt-1 text-xs text-muted">{t.guilds.motdLimit}</p>
                      </div>
                      <button
                        type="submit"
                        disabled={busy}
                        className="rounded-lg bg-brand px-4 py-2 text-sm font-medium text-background disabled:opacity-50"
                      >
                        {t.guilds.save}
                      </button>
                    </form>

                    <div>
                      <label className="mb-1 block text-sm text-muted">{t.guilds.editLogo}</label>
                      <input
                        type="file"
                        accept=".gif,.jpg,.jpeg,.png,.bmp,image/*"
                        disabled={busy}
                        onChange={(e) => uploadLogo(e.target.files?.[0] ?? null)}
                        className="block w-full text-sm text-muted file:mr-3 file:rounded file:border-0 file:bg-brand/15 file:px-3 file:py-1.5 file:text-brand"
                      />
                      <p className="mt-1 text-xs text-muted">{t.guilds.logoHint}</p>
                    </div>

                    <div className="space-y-3">
                      <h3 className="text-sm font-semibold">{t.guilds.ranksTitle}</h3>
                      <div className="space-y-2">
                        {rankEdits.map((r, idx) => (
                          <div key={r.id} className="flex flex-wrap items-center gap-2 text-sm">
                            <input
                              value={r.name}
                              onChange={(e) => {
                                const next = [...rankEdits];
                                next[idx] = { ...next[idx], name: e.target.value };
                                setRankEdits(next);
                              }}
                              className="min-w-[10rem] flex-1 rounded border border-border bg-background px-2 py-1.5 outline-none focus:border-brand/60"
                            />
                            <select
                              value={r.level}
                              onChange={(e) => {
                                const next = [...rankEdits];
                                next[idx] = { ...next[idx], level: Number(e.target.value) };
                                setRankEdits(next);
                              }}
                              className="rounded border border-border bg-background px-2 py-1.5"
                            >
                              <option value={3}>{t.guilds.levelLeader}</option>
                              <option value={2}>{t.guilds.levelVice}</option>
                              <option value={1}>{t.guilds.levelMember}</option>
                            </select>
                            <button
                              type="button"
                              disabled={busy || rankEdits.length < 2}
                              className="rounded border border-border px-2 py-1 text-xs text-muted hover:text-brand disabled:opacity-40"
                              onClick={() =>
                                manage({ action: "delete_rank", id: data.id, rankId: r.id })
                              }
                            >
                              {t.guilds.deleteRank}
                            </button>
                          </div>
                        ))}
                      </div>
                      <button
                        type="button"
                        disabled={busy}
                        className="rounded-lg bg-brand px-4 py-2 text-sm font-medium text-background disabled:opacity-50"
                        onClick={() =>
                          manage({ action: "save_ranks", id: data.id, ranks: rankEdits })
                        }
                      >
                        {t.guilds.save}
                      </button>
                      <div className="flex flex-wrap gap-2 pt-2">
                        <input
                          value={newRankName}
                          onChange={(e) => setNewRankName(e.target.value)}
                          placeholder={t.guilds.rankName}
                          className="min-w-[10rem] flex-1 rounded border border-border bg-background px-2 py-1.5 text-sm outline-none focus:border-brand/60"
                        />
                        <select
                          value={newRankLevel}
                          onChange={(e) => setNewRankLevel(Number(e.target.value))}
                          className="rounded border border-border bg-background px-2 py-1.5 text-sm"
                        >
                          <option value={3}>{t.guilds.levelLeader}</option>
                          <option value={2}>{t.guilds.levelVice}</option>
                          <option value={1}>{t.guilds.levelMember}</option>
                        </select>
                        <button
                          type="button"
                          disabled={busy || !newRankName.trim()}
                          className="rounded border border-border px-3 py-1.5 text-sm hover:border-brand/60 disabled:opacity-40"
                          onClick={async () => {
                            const ok = await manage({
                              action: "add_rank",
                              id: data.id,
                              name: newRankName.trim(),
                              level: newRankLevel,
                            });
                            if (ok) {
                              setNewRankName("");
                              setNewRankLevel(1);
                            }
                          }}
                        >
                          {t.guilds.addRank}
                        </button>
                      </div>
                    </div>

                    <div className="space-y-3 border-t border-border/50 pt-4">
                      <h3 className="text-sm font-semibold">{t.guilds.passLeadership}</h3>
                      <p className="text-xs text-muted">{t.guilds.passLeadershipHint}</p>
                      <div className="flex flex-wrap gap-2">
                        <select
                          value={passTo}
                          onChange={(e) => setPassTo(e.target.value)}
                          className="min-w-[12rem] flex-1 rounded border border-border bg-background px-2 py-1.5 text-sm"
                        >
                          <option value="">{t.guilds.newOwner}</option>
                          {data.ranks
                            .flatMap((r) => r.members)
                            .filter((m) => !m.isOwner)
                            .map((m) => (
                              <option key={m.name} value={m.name}>
                                {m.name}
                              </option>
                            ))}
                        </select>
                        <button
                          type="button"
                          disabled={busy || !passTo}
                          className="rounded-lg bg-brand px-4 py-2 text-sm font-medium text-background disabled:opacity-50"
                          onClick={async () => {
                            if (!window.confirm(t.guilds.passLeadershipConfirm)) return;
                            await manage({
                              action: "pass_leadership",
                              id: data.id,
                              name: passTo,
                            });
                            setPassTo("");
                          }}
                        >
                          {t.guilds.passLeadership}
                        </button>
                      </div>
                    </div>

                    <div className="space-y-3 border-t border-border/50 pt-4">
                      <h3 className="text-sm font-semibold text-red-400">{t.guilds.deleteGuild}</h3>
                      <p className="text-xs text-muted">{t.guilds.deleteGuildHint}</p>
                      <p className="text-xs text-muted">{t.guilds.deleteGuildConfirm}</p>
                      <div className="flex flex-wrap gap-2">
                        <input
                          value={deleteConfirm}
                          onChange={(e) => setDeleteConfirm(e.target.value)}
                          placeholder={t.guilds.deleteGuildTypeName}
                          className="min-w-[10rem] flex-1 rounded border border-border bg-background px-2 py-1.5 text-sm outline-none focus:border-brand/60"
                        />
                        <button
                          type="button"
                          disabled={busy || deleteConfirm !== data.name}
                          className="rounded-lg border border-red-500/50 px-4 py-2 text-sm font-medium text-red-400 disabled:opacity-40"
                          onClick={async () => {
                            const ok = await manage({
                              action: "delete_guild",
                              id: data.id,
                              confirm: deleteConfirm,
                            });
                            if (ok) {
                              window.location.href = "/guilds/";
                            }
                          }}
                        >
                          {t.guilds.deleteGuild}
                        </button>
                      </div>
                    </div>
                  </>
                )}

                {perms?.canInvite && (
                  <div className="space-y-3">
                    <h3 className="text-sm font-semibold">{t.guilds.inviteTitle}</h3>
                    <div className="flex flex-wrap gap-2">
                      <input
                        value={inviteName}
                        onChange={(e) => setInviteName(e.target.value)}
                        placeholder={t.guilds.invitePlaceholder}
                        className="min-w-[10rem] flex-1 rounded border border-border bg-background px-2 py-1.5 text-sm outline-none focus:border-brand/60"
                      />
                      <button
                        type="button"
                        disabled={busy || !inviteName.trim()}
                        className="rounded-lg bg-brand px-4 py-2 text-sm font-medium text-background disabled:opacity-50"
                        onClick={async () => {
                          const ok = await manage({
                            action: "invite",
                            id: data.id,
                            name: inviteName.trim(),
                          });
                          if (ok) setInviteName("");
                        }}
                      >
                        {t.guilds.invitePlayer}
                      </button>
                    </div>
                    {data.invites.length > 0 && (
                      <ul className="divide-y divide-border/40 text-sm">
                        {data.invites.map((inv) => (
                          <li key={inv.name} className="flex items-center justify-between py-2">
                            <span>{inv.name}</span>
                            <button
                              type="button"
                              disabled={busy}
                              className="text-xs text-muted hover:text-brand"
                              onClick={() =>
                                manage({ action: "cancel_invite", id: data.id, name: inv.name })
                              }
                            >
                              {t.guilds.cancelInvite}
                            </button>
                          </li>
                        ))}
                      </ul>
                    )}
                  </div>
                )}
              </div>
            )}

            {!token && (
              <p className="text-sm text-muted">
                <Link href="/login" className="text-brand hover:underline">
                  {t.login}
                </Link>{" "}
                - {t.guilds.loginToManage}
              </p>
            )}

            {data.stats && (
              <div className="rounded-xl border border-border bg-panel p-6">
                <h3 className="mb-3 text-sm font-semibold">{t.guilds.statsTitle}</h3>
                <dl className="grid grid-cols-1 gap-2 text-sm sm:grid-cols-2">
                  <StatRow k={t.guilds.statsMembers} v={String(data.stats.members)} />
                  <StatRow k={t.guilds.statsOnline} v={String(data.stats.online)} />
                  <StatRow k={t.guilds.statsTotalLevel} v={String(data.stats.totalLevel)} />
                  <StatRow k={t.guilds.statsAvgLevel} v={String(data.stats.avgLevel)} />
                  <StatRow k={t.guilds.statsLowest} v={data.stats.lowest || "-"} />
                  <StatRow k={t.guilds.statsHighest} v={data.stats.highest || "-"} />
                  <StatRow k={t.guilds.statsInvites} v={String(data.stats.invites)} />
                </dl>
              </div>
            )}

            <div className="overflow-hidden rounded-xl border border-border bg-panel">
              <div className="border-b border-border px-4 py-3 text-sm font-semibold">
                {t.guilds.warsTitle}
              </div>
              <GuildWarsList wars={data.wars || []} />
            </div>

            {perms?.isAdmin && (
              <div className="rounded-xl border border-red-500/30 bg-panel p-6">
                <button
                  type="button"
                  disabled={busy}
                  className="rounded border border-red-500/50 px-3 py-1.5 text-xs text-red-400 hover:bg-red-500/10 disabled:opacity-40"
                  onClick={async () => {
                    if (!token || !window.confirm(t.guilds.adminDeleteConfirm)) return;
                    setBusy(true);
                    setErr("");
                    try {
                      const r = await fetch(apiUrl("guild-admin.php"), {
                        method: "POST",
                        headers: authHeaders(true),
                        body: JSON.stringify({ action: "deletebyadmin", id: data.id }),
                      });
                      if (!r.ok) {
                        setErr(t.guilds.actionFailed);
                        return;
                      }
                      window.location.href = "/guilds";
                    } catch {
                      setErr(t.guilds.actionFailed);
                    } finally {
                      setBusy(false);
                    }
                  }}
                >
                  {t.guilds.adminDelete}
                </button>
              </div>
            )}

            {myMembers.size > 0 &&
              [...myMembers].some((n) => n !== data.owner) && (
                <div className="rounded-xl border border-border bg-panel p-6">
                  <h3 className="mb-3 text-sm font-semibold">{t.guilds.leaveGuild}</h3>
                  <ul className="space-y-2">
                    {[...myMembers]
                      .filter((n) => n !== data.owner)
                      .map((n) => (
                        <li key={n} className="flex items-center justify-between gap-3 text-sm">
                          <span>{n}</span>
                          <button
                            type="button"
                            disabled={busy}
                            className="rounded border border-border px-3 py-1 text-xs hover:border-brand/60 disabled:opacity-40"
                            onClick={() => {
                              if (!window.confirm(t.guilds.leaveConfirm)) return;
                              manage({ action: "leave_guild", id: data.id, name: n });
                            }}
                          >
                            {t.guilds.leaveGuild}
                          </button>
                        </li>
                      ))}
                  </ul>
                </div>
              )}

            <div className="overflow-hidden rounded-xl border border-border bg-panel">
              <div className="border-b border-border px-4 py-3 text-sm font-semibold">
                {t.guilds.members}
              </div>
              {data.ranks.length === 0 ? (
                <div className="p-6 text-sm text-muted">{t.common.empty}</div>
              ) : (
                <div className="divide-y divide-border/50">
                  {data.ranks.map((rank) => (
                    <div key={rank.id} className="px-4 py-4">
                      <div className="mb-2 text-xs font-semibold uppercase tracking-wide text-muted">
                        {t.guilds.rank}: {rank.name}
                      </div>
                      {rank.members.length === 0 ? (
                        <p className="text-sm text-muted">-</p>
                      ) : (
                        <ul className="space-y-3">
                          {rank.members.map((m) => (
                            <li
                              key={m.name}
                              className="flex flex-wrap items-center justify-between gap-3 text-sm"
                            >
                              <div className="flex min-w-0 flex-1 flex-col gap-1">
                                <div className="flex flex-wrap items-center gap-3">
                                  <PlayerName name={m.name} look={m.look} size="inline" />
                                  {!canEditNick(m.name) && m.guildNick ? (
                                    <span className="text-muted">({m.guildNick})</span>
                                  ) : null}
                                  <span className="shrink-0 text-muted">
                                    {m.vocation} &middot; Lv {m.level}
                                    {m.online ? (
                                      <span className="ml-2 text-brand">online</span>
                                    ) : null}
                                  </span>
                                </div>
                                {canEditNick(m.name) && (
                                  <div className="flex flex-wrap items-center gap-2 pl-1">
                                    <label className="text-xs text-muted">{t.guilds.guildNick}:</label>
                                    <input
                                      value={nickEdits[m.name] ?? m.guildNick ?? ""}
                                      maxLength={40}
                                      onChange={(e) =>
                                        setNickEdits((prev) => ({
                                          ...prev,
                                          [m.name]: e.target.value,
                                        }))
                                      }
                                      className="min-w-[8rem] rounded border border-border bg-background px-2 py-1 text-xs outline-none focus:border-brand/60"
                                    />
                                    <button
                                      type="button"
                                      disabled={busy}
                                      className="rounded border border-border px-2 py-1 text-xs hover:border-brand/60 disabled:opacity-40"
                                      onClick={() =>
                                        manage({
                                          action: "set_guild_nick",
                                          id: data.id,
                                          name: m.name,
                                          nick: (nickEdits[m.name] ?? "").trim(),
                                        })
                                      }
                                    >
                                      {t.guilds.saveNick}
                                    </button>
                                  </div>
                                )}
                              </div>
                              {(perms?.canKick || perms?.canChangeRank) && !m.isOwner && (
                                <div className="flex flex-wrap items-center gap-2">
                                  {perms.canChangeRank && (
                                    <select
                                      className="rounded border border-border bg-background px-2 py-1 text-xs"
                                      value={m.rankId}
                                      disabled={busy}
                                      onChange={(e) => {
                                        const rankId = Number(e.target.value);
                                        if (rankId === m.rankId) return;
                                        manage({
                                          action: "set_member_rank",
                                          id: data.id,
                                          name: m.name,
                                          rankId,
                                        });
                                      }}
                                    >
                                      {data.allRanks
                                        .filter(
                                          (r) =>
                                            perms.isOwner ||
                                            r.level < perms.level ||
                                            r.id === m.rankId
                                        )
                                        .map((r) => (
                                          <option key={r.id} value={r.id}>
                                            {r.name}
                                          </option>
                                        ))}
                                    </select>
                                  )}
                                  {perms.canKick &&
                                    (perms.isOwner || m.rankLevel < perms.level) && (
                                      <button
                                        type="button"
                                        disabled={busy}
                                        className="rounded border border-border px-2 py-1 text-xs text-muted hover:text-brand disabled:opacity-40"
                                        onClick={() => {
                                          if (!window.confirm(t.guilds.confirmKick)) return;
                                          manage({
                                            action: "kick",
                                            id: data.id,
                                            name: m.name,
                                          });
                                        }}
                                      >
                                        {t.guilds.kick}
                                      </button>
                                    )}
                                </div>
                              )}
                            </li>
                          ))}
                        </ul>
                      )}
                    </div>
                  ))}
                </div>
              )}
            </div>
          </div>
        )}
      </main>
      <Footer />
    </div>
  );
}

function StatRow({ k, v }: { k: string; v: string }) {
  return (
    <div className="flex justify-between gap-4 border-b border-border/40 pb-2">
      <span className="text-muted">{k}</span>
      <span className="font-medium">{v}</span>
    </div>
  );
}
// END CHANGE
