// BEGIN CHANGE: pagina Character - paridade com characters.php (set, quests, dodge)
"use client";

import { useEffect, useState, FormEvent, type ReactNode } from "react";
import Link from "next/link";
import { useI18n } from "@/i18n/LanguageProvider";
import { Navbar } from "@/components/Navbar";
import { Footer } from "@/components/Footer";
import { Outfit } from "@/components/Outfit";
import { ItemIcon } from "@/components/ItemIcon";
import { CollapsiblePanel } from "@/components/CollapsiblePanel";
import {
  apiUrl,
  equipmentEmptyBgUrl,
  equipmentPanelBgUrl,
  equipmentSlotUrl,
  patenteUrl,
  type Look,
} from "@/lib/api";

type EqSlot = { slot: number; itemId: number | null };
type Quest = { name: string; done: boolean };
type Killer =
  | {
      type: "monster";
      monster: string;
      count: number;
      look: Look | null;
      itemId: number | null;
    }
  | {
      type: "player";
      player: string;
      count: number;
      deleted?: boolean;
      look: Look | null;
    }
  | {
      type: "summon";
      monster: string;
      player: string;
      count: number;
      monsterLook: Look | null;
      monsterItem: number | null;
      playerLook: Look | null;
    };
type Death = { date: number; level: number; killers: Killer[] };
// BEGIN CHANGE: progresso de tasks e addons do personagem
type TaskMission = {
  id: number;
  name: string;
  requiredLevel?: number;
  status: "not_started" | "in_progress" | "ready_to_deliver" | "expired";
  kills: number;
  requiredKills: number;
  remaining: number;
  expiresAt?: number;
  monsters: string[];
};
type TaskProgress = {
  points: number;
  rank: string;
  current: TaskMission | null;
  daily: TaskMission | null;
  allCompleted: boolean;
};
type PlayerAddon = {
  outfitId: number;
  name: string;
  level: 1 | 2 | 3;
  lookType: number;
};
type PlayerMount = {
  mountId: number;
  name: string;
  tier: string;
  clientId: number;
  looktype: number;
  speed: number;
};
// END CHANGE

// BEGIN CHANGE: status ativos prey/imbu/finite
type ActiveImbu = {
  id: string;
  label: string;
  expireAt: number;
  remainingSec: number;
};
type ActiveStatus = {
  finite: boolean;
  expPotion: { active: boolean; expireAt?: number; remainingSec?: number };
  favela: boolean;
  castle: boolean;
  imbuements: ActiveImbu[];
  prey: {
    monster: string;
    expireAt: number;
    remainingSec: number;
    expBonus: number;
    lootBonus: number;
  } | null;
  mount: {
    id: number;
    tier: string | null;
    name?: string;
    clientId?: number;
    looktype?: number;
    profileId?: string | null;
    profileLabel?: string | null;
    benefit?: string | null;
    expPct?: number | null;
  } | null;
  highestMountTier?: string | null;
  army: { level: number; rank: string | null };
};
// END CHANGE

// BEGIN CHANGE: Meu poder EXP estimado
type ExpPowerLine = {
  group: "slot" | "engine" | "kill" | string;
  id: string;
  percent: number;
  active: boolean;
  note?: string | null;
};
type ExpPower = {
  formula: string;
  slotSumPercent: number;
  engineSumPercent: number;
  killSumPercent: number;
  multiplierVsStage: number;
  staminaMinutes: number | null;
  staminaBand: string | null;
  staminaKillsExp: boolean;
  lines: ExpPowerLine[];
};
// END CHANGE

type Char = {
  name: string;
  oldName: string | null;
  level: number;
  reset: number;
  vocation: string;
  experience: number;
  magic: number;
  sex: string;
  online: boolean;
  // BEGIN CHANGE: Premium Account da conta
  isPremium: boolean;
  premiumDays: number;
  // END CHANGE
  lastlogin: number;
  created: number;
  position: string | null;
  healthMax: number;
  manaMax: number;
  dodge: number;
  critical: number;
  mining: number;
  residence: string | null;
  balance: number;
  // BEGIN CHANGE: gold breakdown bank/backpack/depot
  bankBalance?: number;
  moneyInventory?: number;
  moneyDepot?: number;
  // END CHANGE
  armyLevel: number;
  armyRank: string | null;
  frags: number;
  marriedTo: string | null;
  comment: string | null;
  guild: string | null;
  guildId: number | null;
  guildRank: string | null;
  skills: { name: string; value: number }[];
  equipment: EqSlot[];
  quests: Quest[];
  taskProgress: TaskProgress;
  addons: PlayerAddon[];
  mounts: PlayerMount[];
  highestMountTier?: string | null;
  // BEGIN CHANGE: status ativos
  activeStatus?: ActiveStatus;
  // END CHANGE
  // BEGIN CHANGE: Meu poder EXP
  expPower?: ExpPower | null;
  // END CHANGE
  // BEGIN CHANGE: enchantments log card
  enchantLogs?: {
    item_name: string;
    item_id: number;
    result: string;
    bonus_json: string;
    bonus_tier: string;
    cost_index: string;
    created_at: string;
  }[];
  // END CHANGE
  deaths: Death[];
  look: Look;
  resetBonus?: {
    rr: number;
    damagePercent: number;
    hpmpPercent: number;
    damageMultiplier: number;
  };
};

type State = "idle" | "loading" | "ok" | "notfound" | "error";

export default function CharacterPage() {
  const { t } = useI18n();
  const [input, setInput] = useState("");
  const [data, setData] = useState<Char | null>(null);
  const [state, setState] = useState<State>("idle");
  // BEGIN CHANGE: modo embed reutiliza exatamente o resultado publico dentro do Admin
  const [embedded, setEmbedded] = useState(false);
  // END CHANGE

  function load(name: string) {
    if (!name) return;
    setState("loading");
    fetch(apiUrl(`character.php?name=${encodeURIComponent(name)}`))
      .then((r) => {
        if (r.status === 404) {
          setState("notfound");
          return null;
        }
        if (!r.ok) throw new Error("http " + r.status);
        return r.json();
      })
      .then((json) => {
        if (json && json.data) {
          setData(json.data);
          setState("ok");
        }
      })
      .catch(() => setState("error"));
  }

  // Soft-nav na mesma rota (/character/?name=) nao remonta a pagina;
  // reage a mudancas da query (Link, pushState, voltar/avancar).
  function syncFromUrl() {
    const params = new URLSearchParams(window.location.search);
    const name = params.get("name") ?? "";
    // BEGIN CHANGE: sem Navbar, busca e Footer quando incorporado no Inspector
    setEmbedded(params.get("embed") === "1");
    // END CHANGE
    setInput(name);
    if (name) {
      load(name);
      window.scrollTo({ top: 0, behavior: "smooth" });
    } else {
      setData(null);
      setState("idle");
    }
  }

  useEffect(() => {
    syncFromUrl();
    const onPop = () => syncFromUrl();
    window.addEventListener("popstate", onPop);
    const push = history.pushState.bind(history);
    const replace = history.replaceState.bind(history);
    history.pushState = (...args: Parameters<History["pushState"]>) => {
      push(...args);
      syncFromUrl();
    };
    history.replaceState = (...args: Parameters<History["replaceState"]>) => {
      replace(...args);
      syncFromUrl();
    };
    return () => {
      window.removeEventListener("popstate", onPop);
      history.pushState = push;
      history.replaceState = replace;
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  function onSubmit(e: FormEvent) {
    e.preventDefault();
    const name = input.trim();
    if (!name) return;
    window.history.replaceState(null, "", `/character/?name=${encodeURIComponent(name)}`);
    // syncFromUrl ja cobre via patch de replaceState
  }

  const fmtDate = (epoch: number) =>
    epoch > 0 ? new Date(epoch * 1000).toLocaleString() : t.character.never;

  return (
    <div className={embedded ? "min-h-screen bg-background" : "flex min-h-screen flex-col"}>
      {!embedded && <Navbar />}
      <main className={embedded ? "w-full p-3 sm:p-4" : "mx-auto w-full max-w-4xl flex-1 px-6 py-14"}>
        {!embedded && (
          <>
            <h1 className="text-3xl font-semibold tracking-tight">{t.character.title}</h1>

            <form onSubmit={onSubmit} className="mt-6 flex gap-2">
              <input
                value={input}
                onChange={(e) => setInput(e.target.value)}
                placeholder={t.character.searchPlaceholder}
                className="flex-1 rounded-lg border border-border bg-panel px-4 py-2 text-sm outline-none focus:border-brand/60"
              />
              <button
                type="submit"
                className="rounded-lg bg-brand px-5 py-2 text-sm font-medium text-background transition-opacity hover:opacity-90"
              >
                {t.character.search}
              </button>
            </form>
          </>
        )}

        <div className={embedded ? "" : "mt-8"}>
          {state === "idle" && <p className="text-muted">{t.character.prompt}</p>}
          {state === "loading" && <p className="text-muted">{t.common.loading}</p>}
          {state === "error" && <p className="text-muted">{t.common.error}</p>}
          {state === "notfound" && <p className="text-muted">{t.character.notFound}</p>}
          {state === "ok" && data && (
            <div className="space-y-6">
              <div className="rounded-xl border border-border bg-panel p-6">
                {/* BEGIN CHANGE: outfit maior + equipamento maior e centralizado */}
                <div className="flex flex-col items-center gap-5">
                  <div className="flex flex-col items-center gap-3 sm:flex-row sm:items-center sm:gap-5">
                    <Outfit look={data.look} size="profile" alt={data.name} />
                    <div className="text-center sm:text-left">
                      <h2 className="text-xl font-semibold">{data.name}</h2>
                      <span
                        className={`mt-1 inline-block rounded-full px-3 py-1 text-xs ${
                          data.online
                            ? "bg-brand/15 text-brand"
                            : "bg-background text-muted"
                        }`}
                      >
                        {data.online ? t.character.online : t.character.offline}
                      </span>
                    </div>
                  </div>
                  <EquipmentGrid slots={data.equipment} title={t.character.equipment} />
                </div>
                {/* END CHANGE */}

                <dl className="mt-6 grid grid-cols-1 gap-x-8 gap-y-3 text-sm sm:grid-cols-2">
                  {/* BEGIN CHANGE: status Premium Account (+ dias restantes) */}
                  <Row
                    k={t.character.accountStatus}
                    v={
                      <span className={data.isPremium ? "font-semibold text-emerald-400" : ""}>
                        {data.isPremium
                          ? `${t.character.premiumAccount} (${data.premiumDays} ${t.character.premiumDays})`
                          : t.character.freeAccount}
                      </span>
                    }
                  />
                  {/* END CHANGE */}
                  {data.position && <Row k={t.character.position} v={data.position} />}
                  {data.oldName && <Row k={t.character.oldName} v={data.oldName} />}
                  <Row
                    k={t.character.sex}
                    v={data.sex === "male" ? t.character.male : t.character.female}
                  />
                  <div className="flex justify-between gap-4 border-b border-border/40 pb-2">
                    <span className="shrink-0 text-muted">{t.character.marital}</span>
                    <span className="text-right font-medium">
                      {data.marriedTo ? (
                        <>
                          {t.character.marriedTo}{" "}
                          <Link
                            href={`/character/?name=${encodeURIComponent(data.marriedTo)}`}
                            className="text-brand hover:underline"
                          >
                            {data.marriedTo}
                          </Link>
                        </>
                      ) : (
                        t.character.single
                      )}
                    </span>
                  </div>
                  <Row k={t.character.vocation} v={data.vocation} />
                  <Row k={t.character.level} v={String(data.level)} />
                  <Row k={t.character.resets} v={String(data.reset)} />
                  {data.resetBonus && (
                    <div className="sm:col-span-2 rounded-lg border border-border/70 bg-background/40 px-4 py-3">
                      <div className="flex flex-wrap items-baseline justify-between gap-2">
                        <span className="text-sm font-semibold">{t.character.resetPower}</span>
                        <Link href="/reset" className="text-xs text-brand hover:underline">
                          {t.character.resetPowerTable}
                        </Link>
                      </div>
                      <p className="mt-1 text-xs text-muted">{t.character.resetPowerHint}</p>
                      <dl className="mt-3 grid grid-cols-1 gap-2 text-sm sm:grid-cols-3">
                        <div className="rounded-md border border-border/50 px-3 py-2">
                          <dt className="text-xs text-muted">{t.character.resetDamage}</dt>
                          <dd className="mt-0.5 font-semibold text-brand">
                            +{data.resetBonus.damagePercent}%
                          </dd>
                        </div>
                        <div className="rounded-md border border-border/50 px-3 py-2">
                          <dt className="text-xs text-muted">{t.character.resetHpMp}</dt>
                          <dd className="mt-0.5 font-semibold text-brand">
                            +{data.resetBonus.hpmpPercent}%
                          </dd>
                        </div>
                        <div className="rounded-md border border-border/50 px-3 py-2">
                          <dt className="text-xs text-muted">{t.character.resetMultiplier}</dt>
                          <dd className="mt-0.5 font-semibold">
                            {data.resetBonus.damageMultiplier.toFixed(2)}x
                          </dd>
                        </div>
                      </dl>
                    </div>
                  )}
                  <Row k={t.character.healthMax} v={String(data.healthMax)} />
                  <Row k={t.character.manaMax} v={String(data.manaMax)} />
                  <Row k={t.character.dodge} v={`Level ${data.dodge}`} />
                  <Row k={t.character.critical} v={`Level ${data.critical}`} />
                  <Row k={t.character.mining} v={`Level ${data.mining}`} />
                  <Row k={t.character.magic} v={String(data.magic)} />
                  <Row k={t.character.experience} v={data.experience.toLocaleString()} />
                  {data.residence && <Row k={t.character.residence} v={data.residence} />}
                  {/* BEGIN CHANGE: total gold includes backpack/depot coins */}
                  <Row
                    k={t.character.balance}
                    v={`${data.balance.toLocaleString()} ${t.character.goldCoins}`}
                  />
                  {(data.moneyInventory != null || data.moneyDepot != null) && (
                    <p className="sm:col-span-2 -mt-2 text-xs text-muted">
                      {t.character.goldBreakdown
                        .replace("{bank}", (data.bankBalance ?? data.balance).toLocaleString())
                        .replace("{inv}", (data.moneyInventory ?? 0).toLocaleString())
                        .replace("{depot}", (data.moneyDepot ?? 0).toLocaleString())}
                    </p>
                  )}
                  {/* END CHANGE */}
                  {data.armyLevel > 0 && (
                    <div className="flex justify-between gap-4 border-b border-border/40 pb-2">
                      <span className="shrink-0 text-muted">{t.character.army}</span>
                      <span className="inline-flex items-center gap-2 text-right font-medium">
                        {/* eslint-disable-next-line @next/next/no-img-element */}
                        <img
                          src={patenteUrl(data.armyLevel)}
                          alt=""
                          width={22}
                          height={22}
                          className="object-contain"
                        />
                        {data.armyRank ?? `Level ${data.armyLevel}`}
                      </span>
                    </div>
                  )}
                  {data.frags > 0 && <Row k={t.character.frags} v={String(data.frags)} />}
                  <div className="flex justify-between gap-4 border-b border-border/40 pb-2">
                    <span className="shrink-0 text-muted">{t.character.guild}</span>
                    <span className="text-right font-medium">
                      {data.guild ? (
                        <>
                          {data.guildRank ? `${data.guildRank} of ` : ""}
                          {data.guildId ? (
                            <Link
                              href={`/guild/?id=${data.guildId}`}
                              className="text-brand hover:underline"
                            >
                              {data.guild}
                            </Link>
                          ) : (
                            data.guild
                          )}
                        </>
                      ) : (
                        t.character.noGuild
                      )}
                    </span>
                  </div>
                  <Row k={t.character.lastLogin} v={fmtDate(data.lastlogin)} />
                  {data.created > 0 && (
                    <Row k={t.character.created} v={fmtDate(data.created)} />
                  )}
                </dl>

                {data.comment && (
                  <div className="mt-4 border-t border-border/40 pt-4 text-sm">
                    <div className="text-muted">{t.character.comment}</div>
                    <p className="mt-1 whitespace-pre-wrap">{data.comment}</p>
                  </div>
                )}
              </div>

              {/* BEGIN CHANGE: task atual, progresso, faltantes e nivel/rank */}
              {data.expPower && <ExpPowerCard power={data.expPower} />}
              {data.activeStatus && <ActiveStatusCard status={data.activeStatus} />}
              <TaskProgressCard progress={data.taskProgress} />
              {/* END CHANGE */}

              {/* BEGIN CHANGE: collapsible secondary sections - addons + mounts com animacao */}
              <Section id="char-addons" title={t.character.addons} defaultOpen={false}>
                {data.addons.length === 0 ? (
                  <p className="text-sm text-muted">{t.character.noAddons}</p>
                ) : (
                  <div className="overflow-x-auto rounded-lg border border-border">
                    <table className="w-full text-left text-sm">
                      <thead className="bg-background text-muted">
                        <tr>
                          <th className="px-3 py-2 w-20" />
                          <th className="px-3 py-2">{t.character.addonOutfit}</th>
                          <th className="px-3 py-2">{t.character.addonLevel}</th>
                          <th className="px-3 py-2">{t.character.addonOwned}</th>
                        </tr>
                      </thead>
                      <tbody>
                        {data.addons.map((addon) => (
                          <tr key={addon.outfitId} className="border-t border-border/50">
                            <td className="px-3 py-2">
                              {addon.lookType > 0 ? (
                                <Outfit
                                  look={{
                                    looktype: addon.lookType,
                                    lookhead: data.look.lookhead,
                                    lookbody: data.look.lookbody,
                                    looklegs: data.look.looklegs,
                                    lookfeet: data.look.lookfeet,
                                    lookaddons: addon.level,
                                    lookmount: 0,
                                  }}
                                  size="inline"
                                  alt={addon.name}
                                />
                              ) : null}
                            </td>
                            <td className="px-3 py-2 font-medium">{addon.name}</td>
                            <td className="px-3 py-2 tabular-nums">{addon.level}</td>
                            <td className="px-3 py-2 text-muted">
                              {addon.level === 1
                                ? t.character.addonFirst
                                : addon.level === 2
                                  ? t.character.addonSecond
                                  : t.character.addonFull}
                            </td>
                          </tr>
                        ))}
                      </tbody>
                    </table>
                  </div>
                )}
              </Section>

              <Section id="char-mounts" title={t.character.mounts} defaultOpen={false}>
                {!(data.mounts?.length) ? (
                  <p className="text-sm text-muted">{t.character.noMounts}</p>
                ) : (
                  <>
                    {data.highestMountTier ? (
                      <p className="mb-3 text-sm text-muted">
                        {t.character.mountHighestTier}:{" "}
                        <span className="font-medium text-foreground">
                          {data.highestMountTier}
                        </span>
                      </p>
                    ) : null}
                    <div className="overflow-x-auto rounded-lg border border-border">
                      <table className="w-full text-left text-sm">
                        <thead className="bg-background text-muted">
                          <tr>
                            <th className="px-3 py-2 w-20" />
                            <th className="px-3 py-2">{t.character.mountName}</th>
                            <th className="px-3 py-2">{t.character.mountTierCol}</th>
                            <th className="px-3 py-2">{t.character.mountIdCol}</th>
                          </tr>
                        </thead>
                        <tbody>
                          {data.mounts.map((mount) => (
                            <tr key={mount.mountId} className="border-t border-border/50">
                              <td className="px-3 py-2">
                                {mount.looktype > 0 ? (
                                  <Outfit
                                    look={{
                                      looktype: mount.looktype,
                                      lookhead: 0,
                                      lookbody: 0,
                                      looklegs: 0,
                                      lookfeet: 0,
                                      lookaddons: 0,
                                      lookmount: 0,
                                    }}
                                    size="inline"
                                    alt={mount.name}
                                  />
                                ) : null}
                              </td>
                              <td className="px-3 py-2 font-medium">{mount.name}</td>
                              <td className="px-3 py-2">{mount.tier || "-"}</td>
                              <td className="px-3 py-2 tabular-nums text-muted">{mount.mountId}</td>
                            </tr>
                          ))}
                        </tbody>
                      </table>
                    </div>
                  </>
                )}
              </Section>
              {/* END CHANGE */}

              {data.skills.length > 0 && (
                <Section id="char-skills" title={t.character.skills}>
                  <div className="grid grid-cols-2 gap-x-8 gap-y-3 text-sm sm:grid-cols-3">
                    {data.skills.map((s) => (
                      <div key={s.name} className="flex justify-between">
                        <span className="text-muted">{s.name}</span>
                        <span className="font-medium">{s.value}</span>
                      </div>
                    ))}
                  </div>
                </Section>
              )}

              {data.quests.length > 0 && (
                <Section id="char-quests" title={t.character.quests} defaultOpen={false}>
                  <ul className="divide-y divide-border/40 text-sm">
                    {data.quests.map((q) => (
                      <li key={q.name} className="flex items-center justify-between py-2">
                        <span>{q.name}</span>
                        {/* eslint-disable-next-line @next/next/no-img-element */}
                        <img
                          src={
                            q.done
                              ? "https://ot.whiteantidote.com/images/true.png"
                              : "https://ot.whiteantidote.com/images/false.png"
                          }
                          alt={q.done ? "yes" : "no"}
                          width={16}
                          height={16}
                        />
                      </li>
                    ))}
                  </ul>
                </Section>
              )}

              {data.deaths.length > 0 && (
                <Section id="char-deaths" title={t.character.deaths} defaultOpen={false}>
                  <ul className="space-y-4 text-sm">
                    {data.deaths.map((d, i) => (
                      <li
                        key={`${d.date}-${i}`}
                        className="border-b border-border/40 pb-4 last:border-0"
                      >
                        <div className="flex flex-wrap gap-x-4 gap-y-1 text-muted">
                          <span>{fmtDate(d.date)}</span>
                          <span>
                            {t.character.levelLabel} {d.level}
                          </span>
                        </div>
                        <div className="mt-2 flex flex-wrap items-center gap-x-1 gap-y-2">
                          <span className="text-muted">{t.character.killedBy}:</span>
                          {d.killers.length === 0 ? (
                            <span>-</span>
                          ) : (
                            d.killers.map((k, ki) => (
                              <span
                                key={ki}
                                className="inline-flex flex-wrap items-center gap-1"
                              >
                                {ki > 0 && (
                                  <span className="text-muted">
                                    {ki === d.killers.length - 1 ? " and " : ", "}
                                  </span>
                                )}
                                <KillerChip killer={k} />
                              </span>
                            ))
                          )}
                        </div>
                      </li>
                    ))}
                  </ul>
                </Section>
              )}
          {/* BEGIN CHANGE: enchantments log card */}
          {data.enchantLogs && data.enchantLogs.length > 0 && (
            <CollapsiblePanel id="wa_panel_enchant" title="Enchantments" defaultOpen={false}>
              <div className="overflow-x-auto">
                <table className="w-full min-w-[480px] text-sm">
                  <thead>
                    <tr className="text-left text-muted">
                      <th className="py-1 pr-2">Item</th>
                      <th className="py-1 pr-2">Result</th>
                      <th className="py-1 pr-2">Bonus</th>
                      <th className="py-1">When</th>
                    </tr>
                  </thead>
                  <tbody>
                    {data.enchantLogs.map((row, i) => (
                      <tr key={i} className="border-t border-border">
                        <td className="py-1 pr-2">{row.item_name}</td>
                        <td className="py-1 pr-2">{row.result}</td>
                        <td className="py-1 pr-2">{row.bonus_json || "-"}</td>
                        <td className="py-1">{new Date(Number(row.created_at) * 1000).toLocaleString()}</td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
            </CollapsiblePanel>
          )}
          {/* END CHANGE */}
            </div>
          )}
        </div>
</main>
      {!embedded && <Footer />}
    </div>
  );
}

// BEGIN CHANGE: card completo do Task System
function formatRemain(sec: number): string {
  if (sec <= 0) return "0m";
  const h = Math.floor(sec / 3600);
  const m = Math.floor((sec % 3600) / 60);
  if (h > 0) return `${h}h ${m}m`;
  return `${m}m`;
}

function formatSignedPct(n: number): string {
  if (n > 0) return `+${n}%`;
  if (n < 0) return `${n}%`;
  return "0%";
}

function ExpPowerCard({ power }: { power: ExpPower }) {
  const { t } = useI18n();
  const labels = t.character.expPowerLabels as Record<string, string>;
  const activeLines = power.lines.filter(
    (l) => l.active && l.group !== "kill" && !(l.percent === 0 && l.id !== "staminaZero")
  );
  const killActive = power.lines.filter((l) => l.active && l.group === "kill");

  return (
    <Section id="char-exp-power" title={t.character.expPowerTitle} defaultOpen>
      {!power.staminaKillsExp ? (
        <p className="mb-3 text-sm text-amber-700 dark:text-amber-400">
          {t.character.expPowerStaminaZero}
        </p>
      ) : (
        <p className="mb-3 text-sm">
          <span className="text-muted">{t.character.expPowerMult}</span>{" "}
          <span className="font-mono font-semibold text-brand">
            x{power.multiplierVsStage}
          </span>
          <span className="text-muted">
            {" "}
            ({formatSignedPct(power.slotSumPercent + power.engineSumPercent)}{" "}
            {t.character.expPowerVsStage})
          </span>
        </p>
      )}
      <p className="mb-3 font-mono text-xs text-muted">{power.formula}</p>
      {activeLines.length === 0 && power.staminaKillsExp ? (
        <p className="text-sm text-muted">{t.character.expPowerNone}</p>
      ) : (
        <ul className="grid gap-2 text-sm sm:grid-cols-2">
          {activeLines.map((line) => (
            <li
              key={`${line.group}-${line.id}`}
              className="rounded-lg border border-border/60 bg-background/40 px-4 py-3"
            >
              <div className="text-xs text-muted">
                {labels[line.id] || line.id}
              </div>
              <div className="mt-1 font-medium tabular-nums">
                {formatSignedPct(line.percent)}
                {line.id === "cast" && line.note === "needs_no_password" ? (
                  <span className="ml-2 text-xs font-normal text-muted">
                    {t.character.expPowerCastNote}
                  </span>
                ) : null}
              </div>
            </li>
          ))}
        </ul>
      )}
      {killActive.length > 0 && (
        <div className="mt-4 border-t border-border/40 pt-3">
          <p className="mb-2 text-xs text-muted">{t.character.expPowerKillNote}</p>
          <ul className="grid gap-2 text-sm sm:grid-cols-2">
            {killActive.map((line) => (
              <li
                key={`kill-${line.id}`}
                className="rounded-lg border border-border/60 bg-background/40 px-4 py-3"
              >
                <div className="text-xs text-muted">
                  {labels[line.id] || line.id}
                  {line.note && line.note.startsWith("tier_")
                    ? ` ${line.note.replace("tier_", "")}`
                    : ""}
                </div>
                <div className="mt-1 font-medium tabular-nums">
                  {formatSignedPct(line.percent)}
                </div>
              </li>
            ))}
          </ul>
        </div>
      )}
      <p className="mt-3 text-xs text-muted">
        <Link href="/reset" className="text-brand hover:underline">
          {t.character.expPowerLinkReset}
        </Link>
        {" - "}
        <Link href="/server-info" className="text-brand hover:underline">
          {t.character.expPowerLinkInfo}
        </Link>
      </p>
    </Section>
  );
}

function ActiveStatusCard({ status }: { status: ActiveStatus }) {
  const { t } = useI18n();
  const on = t.character.statusOn;
  const off = t.character.statusOff;

  return (
    <Section id="char-active" title={t.character.activeStatusTitle} defaultOpen>
      <dl className="grid gap-3 text-sm sm:grid-cols-2">
        <div className="rounded-lg border border-border/60 bg-background/40 px-4 py-3">
          <dt className="text-xs text-muted">{t.character.statusFinite}</dt>
          <dd className="mt-1 font-medium">{status.finite ? on : off}</dd>
        </div>
        <div className="rounded-lg border border-border/60 bg-background/40 px-4 py-3">
          <dt className="text-xs text-muted">{t.character.statusExpPot}</dt>
          <dd className="mt-1 font-medium">
            {status.expPotion.active
              ? `${on} (${formatRemain(status.expPotion.remainingSec || 0)})`
              : off}
          </dd>
        </div>
        <div className="rounded-lg border border-border/60 bg-background/40 px-4 py-3">
          <dt className="text-xs text-muted">{t.character.statusFavela}</dt>
          <dd className="mt-1 font-medium">{status.favela ? on : off}</dd>
        </div>
        <div className="rounded-lg border border-border/60 bg-background/40 px-4 py-3">
          <dt className="text-xs text-muted">{t.character.statusCastle}</dt>
          <dd className="mt-1 font-medium">{status.castle ? on : off}</dd>
        </div>
        <div className="rounded-lg border border-border/60 bg-background/40 px-4 py-3 sm:col-span-2">
          <dt className="text-xs text-muted">{t.character.statusPrey}</dt>
          <dd className="mt-1 font-medium">
            {status.prey ? (
              <>
                {status.prey.monster}{" "}
                <span className="text-muted">
                  (+{status.prey.expBonus}% EXP / +{status.prey.lootBonus}% loot -{" "}
                  {formatRemain(status.prey.remainingSec)})
                </span>
              </>
            ) : (
              off
            )}
          </dd>
        </div>
        <div className="rounded-lg border border-border/60 bg-background/40 px-4 py-3 sm:col-span-2">
          <dt className="text-xs text-muted">{t.character.statusImbu}</dt>
          <dd className="mt-1 font-medium">
            {status.imbuements.length === 0
              ? off
              : status.imbuements
                  .map((i) => `${i.label} (${formatRemain(i.remainingSec)})`)
                  .join(" - ")}
          </dd>
        </div>
        <div className="rounded-lg border border-border/60 bg-background/40 px-4 py-3">
          <dt className="text-xs text-muted">{t.character.statusMount}</dt>
          <dd className="mt-1 font-medium">
            {status.mount ? (
              <span className="inline-flex items-center gap-2">
                {status.mount.looktype && status.mount.looktype > 0 ? (
                  <Outfit
                    look={{
                      looktype: status.mount.looktype,
                      lookhead: 0,
                      lookbody: 0,
                      looklegs: 0,
                      lookfeet: 0,
                      lookaddons: 0,
                      lookmount: 0,
                    }}
                    size="inline"
                    alt={status.mount.name ?? ""}
                  />
                ) : null}
                <span>
                  {status.mount.name ?? `id ${status.mount.id}`}
                  {status.mount.tier
                    ? ` - ${t.character.statusMountTier} ${status.mount.tier}`
                    : ""}
                  {status.mount.profileLabel ? ` - ${status.mount.profileLabel}` : ""}
                </span>
              </span>
            ) : (
              off
            )}
          </dd>
          {status.highestMountTier ? (
            <p className="mt-1 text-xs text-muted">
              {t.character.mountHighestTier}: {status.highestMountTier}
            </p>
          ) : null}
        </div>
        <div className="rounded-lg border border-border/60 bg-background/40 px-4 py-3">
          <dt className="text-xs text-muted">{t.character.statusArmy}</dt>
          <dd className="mt-1 flex items-center gap-2 font-medium">
            {status.army.level > 0 ? (
              <>
                {/* eslint-disable-next-line @next/next/no-img-element */}
                <img
                  src={patenteUrl(status.army.level)}
                  alt=""
                  width={24}
                  height={24}
                  className="h-6 w-6"
                />
                {status.army.rank ?? `Level ${status.army.level}`}
              </>
            ) : (
              off
            )}
          </dd>
        </div>
      </dl>
      <p className="mt-3 text-xs text-muted">
        <Link href="/prey" className="text-brand hover:underline">
          Prey
        </Link>
        {" - "}
        <Link href="/imbuements" className="text-brand hover:underline">
          Imbuements
        </Link>
        {" - "}
        <Link href="/reset" className="text-brand hover:underline">
          Reset
        </Link>
        {" - "}
        <Link href="/mounts" className="text-brand hover:underline">
          Mounts
        </Link>
      </p>
    </Section>
  );
}

function TaskProgressCard({ progress }: { progress: TaskProgress }) {
  const { t } = useI18n();
  const statusLabel = (status: TaskMission["status"]) => {
    if (status === "not_started") return t.character.taskNotStarted;
    if (status === "ready_to_deliver") return t.character.taskReady;
    if (status === "expired") return t.character.taskExpired;
    return t.character.taskInProgress;
  };

  return (
    <Section id="char-tasks" title={t.character.taskTitle}>
      <div className="mb-4 grid gap-3 sm:grid-cols-2">
        <div className="rounded-lg border border-border/60 bg-background/40 px-4 py-3">
          <div className="text-xs text-muted">{t.character.taskLevel}</div>
          <div className="mt-1 font-semibold text-brand">{progress.rank}</div>
        </div>
        <div className="rounded-lg border border-border/60 bg-background/40 px-4 py-3">
          <div className="text-xs text-muted">{t.character.taskPoints}</div>
          <div className="mt-1 font-semibold">{progress.points}</div>
        </div>
      </div>

      {progress.allCompleted ? (
        <p className="text-sm text-brand">{t.character.taskAllCompleted}</p>
      ) : progress.current ? (
        <TaskMissionDetails
          mission={progress.current}
          title={t.character.taskCurrent}
          statusLabel={statusLabel(progress.current.status)}
        />
      ) : (
        <p className="text-sm text-muted">{t.character.taskNone}</p>
      )}

      {progress.daily && (
        <div className="mt-4 border-t border-border/50 pt-4">
          <TaskMissionDetails
            mission={progress.daily}
            title={t.character.taskDaily}
            statusLabel={statusLabel(progress.daily.status)}
          />
        </div>
      )}
    </Section>
  );
}

function TaskMissionDetails({
  mission,
  title,
  statusLabel,
}: {
  mission: TaskMission;
  title: string;
  statusLabel: string;
}) {
  const { t } = useI18n();
  const pct =
    mission.requiredKills > 0
      ? Math.min(100, Math.round((mission.kills / mission.requiredKills) * 100))
      : 0;
  return (
    <div>
      <div className="flex flex-wrap items-start justify-between gap-2">
        <div>
          <div className="text-xs text-muted">{title}</div>
          <h4 className="font-semibold">{mission.name}</h4>
        </div>
        <span className="rounded-full border border-brand/30 bg-brand/10 px-2.5 py-1 text-xs text-brand">
          {statusLabel}
        </span>
      </div>
      <div className="mt-3 h-2 overflow-hidden rounded-full bg-background">
        <div className="h-full rounded-full bg-brand" style={{ width: `${pct}%` }} />
      </div>
      <div className="mt-2 grid gap-2 text-sm sm:grid-cols-3">
        <div>
          <span className="text-muted">{t.character.taskKilled}: </span>
          <strong>{mission.kills}</strong>
        </div>
        <div>
          <span className="text-muted">{t.character.taskRequired}: </span>
          <strong>{mission.requiredKills}</strong>
        </div>
        <div>
          <span className="text-muted">{t.character.taskRemaining}: </span>
          <strong>{mission.remaining}</strong>
        </div>
      </div>
      {mission.requiredLevel != null && (
        <p className="mt-2 text-xs text-muted">
          {t.character.taskRequiredLevel}: {mission.requiredLevel}
        </p>
      )}
      {mission.expiresAt != null && mission.expiresAt > 0 && (
        <p className="mt-2 text-xs text-muted">
          {t.character.taskDeadline}: {new Date(mission.expiresAt * 1000).toLocaleString()}
        </p>
      )}
      {mission.monsters.length > 0 && (
        <p className="mt-2 text-xs text-muted">
          {t.character.taskMonsters}: {mission.monsters.join(", ")}
        </p>
      )}
    </div>
  );
}
// END CHANGE

function Section({
  id,
  title,
  children,
  defaultOpen = true,
}: {
  id: string;
  title: string;
  children: ReactNode;
  defaultOpen?: boolean;
}) {
  return (
    <CollapsiblePanel id={id} title={title} defaultOpen={defaultOpen}>
      {children}
    </CollapsiblePanel>
  );
}

function Row({ k, v }: { k: string; v: ReactNode }) {
  return (
    <div className="flex justify-between gap-4 border-b border-border/40 pb-2">
      <span className="shrink-0 text-muted">{k}</span>
      <span className="text-right font-medium">{v}</span>
    </div>
  );
}

function EquipmentGrid({ slots, title }: { slots: EqSlot[]; title: string }) {
  // Ordem legado: 2,1,3 / 6,4,5 / 9,7,10 / _,8 - feet (8) centralizado na 4a linha
  const cells: (EqSlot | null)[] = [...slots];
  // Inserir celula vazia antes do feet (slot 8) para centralizar
  const feetIdx = cells.findIndex((c) => c && c.slot === 8);
  if (feetIdx >= 0) {
    cells.splice(feetIdx, 0, null);
  }

  // BEGIN CHANGE: slots/itens maiores (48px) e bloco centralizado
  const slotPx = 48;
  const iconPx = 40;
  return (
    <div className="mx-auto w-fit">
      <div className="mb-2 text-center text-sm text-muted">{title}</div>
      <div
        className="inline-grid grid-cols-3 gap-1 rounded border border-black/80 p-1.5"
        style={{ backgroundImage: `url(${equipmentPanelBgUrl()})` }}
      >
        {cells.map((cell, i) => {
          if (!cell) {
            return (
              <div
                key={`empty-${i}`}
                style={{ width: slotPx, height: slotPx }}
              />
            );
          }
          const filled = cell.itemId != null && cell.itemId > 0;
          return (
            <div
              key={cell.slot}
              className="flex items-center justify-center"
              style={{
                width: slotPx,
                height: slotPx,
                ...(filled
                  ? { backgroundImage: `url(${equipmentEmptyBgUrl()})` }
                  : {}),
              }}
              title={filled ? `Item ${cell.itemId}` : `Slot ${cell.slot}`}
            >
              {filled ? (
                <ItemIcon id={cell.itemId!} size={iconPx} />
              ) : (
                // eslint-disable-next-line @next/next/no-img-element
                <img
                  src={equipmentSlotUrl(cell.slot)}
                  alt=""
                  width={iconPx}
                  height={iconPx}
                  className="object-contain"
                  style={{ width: iconPx, height: iconPx }}
                />
              )}
            </div>
          );
        })}
      </div>
    </div>
  );
  // END CHANGE
}

function KillerChip({ killer }: { killer: Killer }) {
  const countPrefix = killer.count > 1 ? `${killer.count}x ` : "";
  // Outfits maiores no painel de mortes (legado ~64px)
  const outfitSize = "row" as const;

  if (killer.type === "monster") {
    return (
      <span className="inline-flex items-center gap-2">
        <MonsterVisual
          look={killer.look}
          itemId={killer.itemId}
          alt={killer.monster}
          size={outfitSize}
        />
        <span>
          {countPrefix}
          {killer.monster}
        </span>
      </span>
    );
  }

  if (killer.type === "player") {
    const canLink = !killer.deleted;
    const inner = (
      <>
        {killer.look && (
          <Outfit look={killer.look} size={outfitSize} alt={killer.player} />
        )}
        <span className="font-medium">{killer.player}</span>
      </>
    );
    if (!canLink) {
      return <span className="inline-flex items-center gap-2">{inner}</span>;
    }
    return (
      <Link
        href={`/character/?name=${encodeURIComponent(killer.player)}`}
        className="inline-flex items-center gap-2 text-brand hover:underline"
      >
        {inner}
      </Link>
    );
  }

  // summon
  return (
    <span className="inline-flex flex-wrap items-center gap-2">
      <MonsterVisual
        look={killer.monsterLook}
        itemId={killer.monsterItem}
        alt={killer.monster}
        size={outfitSize}
      />
      <span>
        {countPrefix}
        {killer.monster}
      </span>
      <span className="text-muted">summoned by</span>
      <Link
        href={`/character/?name=${encodeURIComponent(killer.player)}`}
        className="inline-flex items-center gap-2 text-brand hover:underline"
      >
        {killer.playerLook && (
          <Outfit look={killer.playerLook} size={outfitSize} alt={killer.player} />
        )}
        <span className="font-medium">{killer.player}</span>
      </Link>
    </span>
  );
}

function MonsterVisual({
  look,
  itemId,
  alt,
  size = "row",
}: {
  look: Look | null;
  itemId: number | null;
  alt: string;
  size?: "inline" | "row" | "grid" | "profile";
}) {
  if (look && look.looktype > 0) {
    return <Outfit look={look} size={size} alt={alt} />;
  }
  if (itemId && itemId > 0) {
    return <ItemIcon id={itemId} size={40} alt={alt} />;
  }
  return null;
}
// END CHANGE
