import {
  fetchUserProfile,
  notifyApiFailure,
  notifyDbFailure,
  postLogout,
  postProfileComplete,
  postPasswordChange,
  postUserCrypto,
  postUserSponsorAccounts,
  postUser2fa,
} from "../auth/session.js";
import { mountProfileTelegramInvite } from "../components/profile-telegram-invite.js";
import { showToast } from "../components/toast.js";
import { t, getSiteLocale, dataJsonUrl } from "../config/site.js";

const CRYPTO_FIELD_DEFS = [
  {
    key: "btc",
    label: "BTC",
    placeholderKey: "profileCryptoPlaceholderBtc",
    ring: "ring-sky-500/40",
    iconBg: "bg-sky-500/20 text-sky-300",
    icon: "₿",
  },
  {
    key: "eth",
    label: "ETH",
    placeholderKey: "profileCryptoPlaceholderEth",
    ring: "ring-indigo-400/40",
    iconBg: "bg-indigo-500/20 text-indigo-200",
    icon: "Ξ",
  },
  {
    key: "usdtErc20",
    label: "USDT ERC-20",
    placeholderKey: "profileCryptoPlaceholderUsdtErc",
    ring: "ring-sky-400/40",
    iconBg: "bg-sky-600/25 text-sky-200",
    icon: "₮",
    badge: "E",
  },
  {
    key: "usdtTrc20",
    label: "USDT TRC-20",
    placeholderKey: "profileCryptoPlaceholderUsdtTrc",
    ring: "ring-sky-400/40",
    iconBg: "bg-sky-600/25 text-sky-200",
    icon: "₮",
    badge: "TR",
  },
  {
    key: "ltc",
    label: "LTC",
    placeholderKey: "profileCryptoPlaceholderLtc",
    ring: "ring-slate-400/40",
    iconBg: "bg-slate-500/25 text-slate-200",
    icon: "Ł",
  },
  {
    key: "trx",
    label: "TRX",
    placeholderKey: "profileCryptoPlaceholderTrx",
    ring: "ring-red-400/40",
    iconBg: "bg-red-600/25 text-red-100",
    icon: "T",
  },
  {
    key: "doge",
    label: "DOGE",
    placeholderKey: "profileCryptoPlaceholderDoge",
    ring: "ring-sky-400/40",
    iconBg: "bg-sky-500/25 text-sky-100",
    icon: "Ð",
  },
  {
    key: "other",
    labelKey: "profileCryptoOtherLabel",
    placeholderKey: "profileCryptoPlaceholderOther",
    ring: "ring-sky-500/40",
    iconBg: "bg-sky-600/20 text-sky-100",
    icon: "◎",
  },
];

function getCryptoFields() {
  return CRYPTO_FIELD_DEFS.map((f) => ({
    ...f,
    label: f.labelKey ? t(f.labelKey) : f.label,
    placeholder: t(f.placeholderKey),
  }));
}

function cryptoCardHtml(f) {
  const badge = f.badge
    ? `<span class="absolute -bottom-0.5 -right-0.5 flex h-5 min-w-[1.25rem] items-center justify-center rounded-full bg-slate-900/90 px-1 text-[10px] font-bold text-white ring-1 ring-white/20">${f.badge}</span>`
    : "";
  return `
    <div class="profile-card p-4 shadow-panel ring-1 ${f.ring}">
      <div class="mb-3 flex items-center gap-3">
        <div class="relative flex h-12 w-12 shrink-0 items-center justify-center rounded-full text-lg font-bold ${f.iconBg}">
          ${f.icon}
          ${badge}
        </div>
        <div class="min-w-0">
          <p class="text-sm font-semibold text-white">${f.label}</p>
          <p class="text-[11px] text-slate-500">${t("profileWalletAddress")}</p>
        </div>
      </div>
      <input
        type="text"
        name="${f.key}"
        data-crypto-input
        autocomplete="off"
        spellcheck="false"
        placeholder="${f.placeholder}"
        class="input-site-field w-full text-sm"
      />
    </div>
  `;
}

function sponsorAccountRowHtml(sponsor, value = "") {
  const sid = escapeHtml(String(sponsor.id || ""));
  const title = escapeHtml(String(sponsor.title || sid));
  const val = escapeHtml(String(value || ""));
  return `
    <div class="profile-field p-3">
      <label class="mb-1.5 block text-[11px] font-semibold uppercase tracking-wide text-slate-500">${title}</label>
      <input
        type="text"
        class="input-site-field w-full text-sm"
        data-sponsor-id="${sid}"
        data-sponsor-title="${title}"
        value="${val}"
        placeholder="${t("profileSponsorAccountPlaceholder")}"
        maxlength="200"
      />
    </div>
  `;
}

async function loadSponsorsForProfile() {
  try {
    const r = await fetch(dataJsonUrl("sponsors.json"), { cache: "default" });
    if (!r.ok) return [];
    const j = await r.json();
    return Array.isArray(j) ? j : [];
  } catch {
    return [];
  }
}

const PROFILE_TABS = ["info", "telegram", "crypto", "sponsors", "wheel", "purchases", "blackjack", "slot", "roulette", "complaints"];

function blackjackOutcomeBadge(outcome) {
  const o = String(outcome || "");
  if (o === "win") {
    return `<span class="inline-flex items-center rounded-md border border-sky-500/35 bg-sky-500/15 px-2 py-0.5 text-xs font-semibold text-sky-200">${t("profileBjWin")}</span>`;
  }
  if (o === "lose") {
    return `<span class="inline-flex items-center rounded-md border border-rose-500/35 bg-rose-500/15 px-2 py-0.5 text-xs font-semibold text-rose-200">${t("profileBjLose")}</span>`;
  }
  if (o === "push") {
    return `<span class="inline-flex items-center rounded-md border border-slate-500/35 bg-slate-500/15 px-2 py-0.5 text-xs font-semibold text-slate-200">${t("profileBjPush")}</span>`;
  }
  if (o === "blackjack") {
    return `<span class="inline-flex items-center rounded-md border border-sky-500/35 bg-sky-500/15 px-2 py-0.5 text-xs font-semibold text-sky-200">${t("profileBjBlackjack")}</span>`;
  }
  return `<span class="inline-flex items-center rounded-md border border-white/20 bg-white/10 px-2 py-0.5 text-xs font-semibold text-slate-300">${escapeHtml(o)}</span>`;
}

function blackjackRoundCardHtml(r) {
  const stake = Number(r.stake) || 0;
  const payout = Number(r.payout) || 0;
  const net = payout - stake;
  const netStr = net > 0 ? `+${net}` : String(net);
  const netClass = net > 0 ? "text-sky-300" : net < 0 ? "text-rose-300" : "text-slate-400";
  const bet = Number(r.bet) || 0;
  const doubled = !!r.doubled;
  return `
    <div class="profile-row flex flex-col gap-2 px-4 py-3 sm:flex-row sm:items-center sm:justify-between">
      <div class="min-w-0">
        <div class="flex flex-wrap items-center gap-2">
          ${blackjackOutcomeBadge(r.outcome)}
          <span class="text-xs text-slate-500">${formatTs(r.createdAt)}</span>
        </div>
        <p class="mt-2 text-xs leading-relaxed text-slate-400">
          ${t("profileBjBet")} <span class="font-semibold text-slate-300">${bet}</span> ${t("marketCoinWord")}
          · ${doubled ? t("profileBjDouble") : t("profileBjNormal")}
          · ${t("profileBjRisk")} <span class="tabular-nums text-slate-300">${stake}</span> ${t("marketCoinWord")}
          · ${t("profileBjPayout")} <span class="tabular-nums text-slate-300">${payout}</span> ${t("marketCoinWord")}
        </p>
      </div>
      <div class="shrink-0 text-right text-sm font-semibold tabular-nums ${netClass}">${t("profileBjNet")} ${netStr} ${t("marketCoinWord")}</div>
    </div>`;
}

const SLOT_SYM_EMOJI = {
  cherry: "🍒",
  lemon: "🍋",
  bell: "🔔",
  diamond: "💎",
  seven: "7️⃣",
};

function slotRoundCardHtml(r) {
  const reels = Array.isArray(r.reels) ? r.reels : [];
  const line = reels.map((id) => SLOT_SYM_EMOJI[String(id)] || "·").join(" ");
  const bet = Number(r.bet) || 0;
  const payout = Number(r.payout) || 0;
  const mult = Number(r.multiplier) || 0;
  const net = payout - bet;
  const netStr = net > 0 ? `+${net}` : String(net);
  const netClass = net > 0 ? "text-sky-300" : net < 0 ? "text-rose-300" : "text-slate-400";
  const badge =
    mult > 0
      ? `<span class="inline-flex items-center rounded-md border border-fuchsia-500/35 bg-fuchsia-500/15 px-2 py-0.5 text-xs font-semibold text-fuchsia-200">${mult}×</span>`
      : `<span class="inline-flex items-center rounded-md border border-slate-500/35 bg-slate-500/15 px-2 py-0.5 text-xs font-semibold text-slate-300">${t("profileSlotLoss")}</span>`;
  return `
    <div class="profile-row flex flex-col gap-2 px-4 py-3 sm:flex-row sm:items-center sm:justify-between">
      <div class="min-w-0">
        <div class="flex flex-wrap items-center gap-2">
          ${badge}
          <span class="text-lg leading-none tracking-tight" title="${t("profileSlotReel")}">${line}</span>
          <span class="text-xs text-slate-500">${formatTs(r.createdAt)}</span>
        </div>
        <p class="mt-2 text-xs leading-relaxed text-slate-400">
          ${t("profileBjBet")} <span class="font-semibold text-slate-300">${bet}</span> ${t("marketCoinWord")}
          · ${t("profileBjPayout")} <span class="tabular-nums text-slate-300">${payout}</span> ${t("marketCoinWord")}
        </p>
      </div>
      <div class="shrink-0 text-right text-sm font-semibold tabular-nums ${netClass}">${t("profileBjNet")} ${netStr} ${t("marketCoinWord")}</div>
    </div>`;
}

function rouletteRoundCardHtml(r) {
  const bet = Number(r.bet) || 0;
  const payout = Number(r.payout) || 0;
  const mult = Number(r.multiplier) || 0;
  const net = payout - bet;
  const netStr = net > 0 ? `+${net}` : String(net);
  const netClass = net > 0 ? "text-sky-300" : net < 0 ? "text-rose-300" : "text-slate-400";
  const bt = String(r.betType || "");
  const bv = r.betValue;
  let betLine = bt;
  if (bt === "straight") {
    betLine = `${t("rouletteBetStraight")} ${bv != null ? String(bv) : "—"}`;
  } else if (bt === "red") betLine = t("rouletteBetRed");
  else if (bt === "black") betLine = t("rouletteBetBlack");
  else if (bt === "even") betLine = t("rouletteBetEven");
  else if (bt === "odd") betLine = t("rouletteBetOdd");
  else if (bt === "low") betLine = t("rouletteBetLow");
  else if (bt === "high") betLine = t("rouletteBetHigh");
  else if (bt === "dozen") betLine = t("rouletteBetDozen").replace("{n}", bv != null ? String(bv) : "—");
  else if (bt === "column") betLine = t("rouletteBetColumn").replace("{n}", bv != null ? String(bv) : "—");
  const wn = Number(r.winningNumber);
  const badge =
    mult > 0
      ? `<span class="inline-flex items-center rounded-md border border-sky-500/35 bg-sky-500/15 px-2 py-0.5 text-xs font-semibold text-sky-200">${mult}×</span>`
      : `<span class="inline-flex items-center rounded-md border border-slate-500/35 bg-slate-500/15 px-2 py-0.5 text-xs font-semibold text-slate-300">${t("profileRouletteLoss")}</span>`;
  return `
    <div class="profile-row flex flex-col gap-2 px-4 py-3 sm:flex-row sm:items-center sm:justify-between">
      <div class="min-w-0">
        <div class="flex flex-wrap items-center gap-2">
          ${badge}
          <span class="text-xs font-semibold text-slate-200">${t("rouletteResult")}: ${Number.isFinite(wn) ? wn : "—"}</span>
          <span class="text-xs text-slate-500">${formatTs(r.createdAt)}</span>
        </div>
        <p class="mt-2 text-xs leading-relaxed text-slate-400">
          ${t("profileRouletteBet")}: <span class="text-slate-300">${escapeHtml(betLine)}</span>
          · ${t("profileBjBet")} <span class="font-semibold text-slate-300">${bet}</span> ${t("marketCoinWord")}
          · ${t("profileBjPayout")} <span class="tabular-nums text-slate-300">${payout}</span> ${t("marketCoinWord")}
        </p>
      </div>
      <div class="shrink-0 text-right text-sm font-semibold tabular-nums ${netClass}">${t("profileBjNet")} ${netStr} ${t("marketCoinWord")}</div>
    </div>`;
}

function profileTabButtonClass(active) {
  const layout =
    "profile-tab w-full min-h-[2.75rem] items-center justify-center text-center text-sm leading-snug lg:min-h-0 lg:w-auto lg:px-3";
  return active
    ? `k-tab k-tab--active inline-flex ${layout} rounded-xl border border-accent/45 bg-accent/20 px-2 py-2 font-semibold text-accent ring-1 ring-accent/25`
    : `k-tab profile-tab-idle inline-flex ${layout} rounded-xl border px-2 py-2 font-medium transition`;
}

function initProfileTwofa(root, twofa) {
  const enabled = twofa?.enabled === true;
  const statusEl = root.querySelector("#profile-twofa-status");
  const actionsEl = root.querySelector("#profile-twofa-actions");
  const setupEl = root.querySelector("#profile-twofa-setup");
  const errEl = root.querySelector("#profile-twofa-error");
  const card = root.querySelector("#profile-twofa-card");
  if (!statusEl || !actionsEl || !card) return;

  const showErr = (msg) => {
    if (!errEl) return;
    if (!msg) {
      errEl.classList.add("hidden");
      errEl.textContent = "";
      return;
    }
    errEl.textContent = msg;
    errEl.classList.remove("hidden");
  };

  statusEl.textContent = enabled ? t("profileTwofaStatusOn") : t("profileTwofaStatusOff");
  if (enabled) {
    statusEl.classList.add("text-emerald-300");
    actionsEl.innerHTML = "";
    setupEl?.classList.add("hidden");
    root.querySelector("#profile-twofa-active-hint")?.remove();
    const hint = document.createElement("p");
    hint.id = "profile-twofa-active-hint";
    hint.className = "mt-3 text-sm text-slate-400";
    hint.textContent = t("profileTwofaActiveHint");
    card.appendChild(hint);
    return;
  }

  statusEl.classList.remove("text-emerald-300");
  actionsEl.innerHTML = `<button type="button" id="profile-twofa-start" class="k-btn k-btn--primary btn-site-primary rounded-xl px-4 py-2 text-sm font-semibold">${t("profileTwofaSetupBtn")}</button>`;
  setupEl?.classList.add("hidden");

  root.querySelector("#profile-twofa-start")?.addEventListener("click", async () => {
    showErr("");
    const res = await postUser2fa({ action: "start_setup" });
    if (!res.ok) {
      notifyApiFailure();
      return;
    }
    const setup = res.data?.setup || {};
    setupEl?.classList.remove("hidden");
    const qr = root.querySelector("#profile-twofa-qr");
    if (qr instanceof HTMLImageElement && setup.qrUrl) {
      qr.src = setup.qrUrl;
      qr.alt = "2FA QR";
    }
    const secretEl = root.querySelector("#profile-twofa-secret");
    if (secretEl) secretEl.textContent = setup.secret || "";
    root.querySelector("#profile-twofa-code")?.focus();
  });

  root.querySelector("#profile-twofa-confirm")?.addEventListener("click", async () => {
    showErr("");
    const code = root.querySelector("#profile-twofa-code")?.value?.trim() || "";
    if (!code) {
      showErr(t("profileTwofaInvalid"));
      return;
    }
    const res = await postUser2fa({ action: "confirm_setup", code });
    if (!res.ok) {
      showErr(t("profileTwofaInvalid"));
      return;
    }
    showToast(t("profileTwofaEnabledToast"), "success");
    initProfileTwofa(root, { enabled: true });
  });
}

function setActiveProfileTab(root, tab) {
  const normalized = PROFILE_TABS.includes(tab) ? tab : "info";
  root.querySelectorAll("[data-profile-tab]").forEach((btn) => {
    const isActive = btn.getAttribute("data-profile-tab") === normalized;
    btn.className = profileTabButtonClass(isActive);
    btn.setAttribute("aria-selected", isActive ? "true" : "false");
  });
  root.querySelectorAll("[data-profile-panel]").forEach((panel) => {
    const isActive = panel.getAttribute("data-profile-panel") === normalized;
    panel.classList.toggle("hidden", !isActive);
  });
}

function profileUserInitial(username) {
  const u = String(username || "U").trim();
  if (!u) return "U";
  return u.slice(0, 1).toLocaleUpperCase(getSiteLocale() === "en" ? "en" : "tr");
}

function updateProfileHero(root, user, level) {
  const hero = root.querySelector("#profile-hero");
  if (!hero) return;

  const locale = getSiteLocale() === "en" ? "en-US" : "tr-TR";
  const fmt = (n) => Number(n).toLocaleString(locale);

  if (!user) {
    hero.classList.add("profile-hero--guest");
    hero.classList.remove("profile-hero--ready");
    const nameEl = hero.querySelector("#profile-hero-name");
    const metaEl = hero.querySelector("#profile-hero-meta");
    const avatarEl = hero.querySelector("#profile-hero-avatar");
    if (nameEl) nameEl.textContent = t("profileTitle");
    if (metaEl) metaEl.textContent = t("profileSubtitle");
    if (avatarEl) avatarEl.textContent = "?";
    return;
  }

  hero.classList.remove("profile-hero--guest");
  hero.classList.add("profile-hero--ready");

  const name = user.username ? String(user.username) : "—";
  const coins = Number(user.coins) || 0;
  const lvNo = Math.max(0, Number(level?.level) || 0);
  const xpTotal = Math.max(0, Number(level?.xpTotal) || 0);
  const xpInLevel = Math.max(0, Number(level?.xpInLevel) || 0);
  const xpToNext = Math.max(0, Number(level?.xpToNext) || 0);
  const progress = Math.max(0, Math.min(100, Number(level?.progressPercent) || 0));
  const xpNeeded = Math.max(0, Number(level?.xpNeeded) || 0);
  const xpMaxInBar = xpNeeded > 0 ? xpNeeded : xpInLevel;

  const nameEl = hero.querySelector("#profile-hero-name");
  const metaEl = hero.querySelector("#profile-hero-meta");
  const avatarEl = hero.querySelector("#profile-hero-avatar");
  const levelEl = hero.querySelector("#profile-hero-level");
  const coinsEl = hero.querySelector("#profile-hero-coins");
  const xpBarEl = hero.querySelector("#profile-hero-xp-bar");
  const xpTotalEl = hero.querySelector("#profile-hero-xp-total");
  const xpFillEl = hero.querySelector("#profile-hero-xp-fill");
  const xpPctEl = hero.querySelector("#profile-hero-xp-pct");
  const rankEl = hero.querySelector("#profile-hero-rank");
  const xpTrack = hero.querySelector("#profile-hero-xp-track");

  if (nameEl) nameEl.textContent = name;
  if (avatarEl) avatarEl.textContent = profileUserInitial(name);
  if (rankEl) rankEl.textContent = t("profileHeroRank").replace("{n}", String(lvNo));
  if (metaEl) {
    const memberLine =
      user.createdAt > 0
        ? t("profileHeroMemberSince").replace("{date}", formatTs(user.createdAt))
        : t("profileSubtitle");
    metaEl.textContent = memberLine;
  }
  if (levelEl) levelEl.textContent = String(lvNo);
  if (coinsEl) coinsEl.textContent = fmt(coins);
  if (xpBarEl) {
    const nextLv = Number(level?.nextLevel) || lvNo + 1;
    xpBarEl.textContent =
      xpNeeded > 0
        ? t("profileHeroXpBar")
            .replace("{cur}", fmt(xpInLevel))
            .replace("{max}", fmt(xpMaxInBar))
            .replace("{next}", String(nextLv))
        : t("profileLevelMax");
  }
  if (xpTotalEl) {
    xpTotalEl.textContent = t("profileHeroXpTotal").replace("{n}", fmt(xpTotal));
  }
  if (xpFillEl instanceof HTMLElement) {
    xpFillEl.style.width = `${progress}%`;
  }
  if (xpPctEl) xpPctEl.textContent = `${progress}%`;
  if (xpTrack instanceof HTMLElement) {
    xpTrack.setAttribute("aria-valuenow", String(progress));
    xpTrack.setAttribute(
      "aria-label",
      xpNeeded > 0
        ? t("profileHeroXpBar")
            .replace("{cur}", fmt(xpInLevel))
            .replace("{max}", fmt(xpMaxInBar))
            .replace("{next}", String(Number(level?.nextLevel) || lvNo + 1))
        : t("profileLevelMax")
    );
  }
}

const PROFILE_HERO_ICON_LEVEL = `<svg fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"/></svg>`;
const PROFILE_HERO_ICON_COIN = `<svg fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8c-2.21 0-4 1.343-4 3s1.79 3 4 3 4 1.343 4 3-1.79 3-4 3m0-12c2.21 0 4 1.343 4 3M12 2v2m0 16v2"/></svg>`;

export function renderProfile(root) {
  root.innerHTML = `
    <section class="k-page k-page--profile relative mx-auto max-w-6xl space-y-8 px-1 pb-4">
      <header id="profile-hero" class="profile-hero profile-hero--guest" aria-label="${escapeHtml(t("profileTitle"))}">
        <div class="profile-hero__mesh" aria-hidden="true"></div>
        <div class="profile-hero__glow" aria-hidden="true"></div>
        <div class="profile-hero__content">
          <div class="profile-hero__top">
            <div class="profile-hero__user min-w-0">
              <span class="profile-hero__eyebrow">
                <span class="profile-hero__eyebrow-dot" aria-hidden="true"></span>
                ${escapeHtml(t("profileEyebrow"))}
              </span>
              <div class="profile-hero__identity">
                <div class="profile-hero__avatar-wrap">
                  <span class="profile-hero__avatar-ring" aria-hidden="true"></span>
                  <span id="profile-hero-avatar" class="profile-hero__avatar" aria-hidden="true">?</span>
                </div>
                <div class="min-w-0">
                  <div class="profile-hero__name-row">
                    <h1 id="profile-hero-name" class="profile-hero__name">${escapeHtml(t("profileTitle"))}</h1>
                    <span id="profile-hero-rank" class="profile-hero__rank-pill">${escapeHtml(t("profileHeroRank").replace("{n}", "0"))}</span>
                  </div>
                  <p id="profile-hero-meta" class="profile-hero__meta">${escapeHtml(t("profileSubtitle"))}</p>
                </div>
              </div>
            </div>
            <div class="profile-hero__stats">
              <div class="profile-hero__stat" title="${escapeHtml(t("profileHeroLevel"))}">
                <span class="profile-hero__stat-icon">${PROFILE_HERO_ICON_LEVEL}</span>
                <span class="profile-hero__stat-body">
                  <span class="profile-hero__stat-label">LV</span>
                  <span id="profile-hero-level" class="profile-hero__stat-value">0</span>
                </span>
              </div>
              <div class="profile-hero__stat profile-hero__stat--coins" title="${escapeHtml(t("headerCoinBalance"))}">
                <span class="profile-hero__stat-icon">${PROFILE_HERO_ICON_COIN}</span>
                <span class="profile-hero__stat-body">
                  <span class="profile-hero__stat-label">${escapeHtml(t("marketCoinWord"))}</span>
                  <span id="profile-hero-coins" class="profile-hero__stat-value">0</span>
                </span>
              </div>
            </div>
          </div>
          <div class="profile-hero__xp-panel">
            <div class="profile-hero__xp-header">
              <div>
                <span class="profile-hero__xp-title">${escapeHtml(t("profileHeroProgress"))}</span>
                <p id="profile-hero-xp-total" class="profile-hero__xp-sub">${escapeHtml(t("profileHeroXpTotal").replace("{n}", "0"))}</p>
              </div>
              <span id="profile-hero-xp-bar" class="profile-hero__xp-target">${escapeHtml(t("profileLevelNext"))}</span>
            </div>
            <div class="profile-hero__xp-track-wrap">
              <div class="profile-hero__xp-track" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0" id="profile-hero-xp-track">
                <div id="profile-hero-xp-fill" class="profile-hero__xp-fill" style="width:0%"></div>
              </div>
              <span id="profile-hero-xp-pct" class="profile-hero__xp-pct">0%</span>
            </div>
          </div>
        </div>
      </header>

      <section id="profile-loading-gate" class="rounded-3xl border border-white/[0.08] bg-[#1e2739] p-6 text-sm text-slate-300 shadow-panel ring-1 ring-white/[0.05]">
        <p class="font-medium text-white">${t("profileLoadingTitle")}</p>
        <p class="mt-1 text-slate-400">${t("profileLoadingHint")}</p>
      </section>

      <section id="profile-auth-gate" class="hidden rounded-3xl border border-white/[0.08] bg-[#1e2739] p-6 text-sm text-slate-300 shadow-panel ring-1 ring-white/[0.05]">
        <p class="font-medium text-white">${t("profileAuthTitle")}</p>
        <p class="mt-1 text-slate-400">${t("profileAuthHint")}</p>
      </section>

      <div id="profile-content" class="hidden space-y-8">
        <section class="rounded-3xl border border-white/[0.08] bg-[#1e2739] p-3 shadow-panel ring-1 ring-white/[0.05] sm:p-4">
          <div class="grid grid-cols-2 gap-2 lg:flex lg:flex-wrap lg:gap-2">
            <button type="button" data-profile-tab="info" class="${profileTabButtonClass(true)}" aria-selected="true">${t("profileTabInfo")}</button>
            <button type="button" data-profile-tab="telegram" class="${profileTabButtonClass(false)}" aria-selected="false">${t("profileTabTelegram")}</button>
            <button type="button" data-profile-tab="crypto" class="${profileTabButtonClass(false)}" aria-selected="false">${t("profileTabCrypto")}</button>
            <button type="button" data-profile-tab="sponsors" class="${profileTabButtonClass(false)}" aria-selected="false">${t("profileTabSponsors")}</button>
            <button type="button" data-profile-tab="wheel" class="${profileTabButtonClass(false)}" aria-selected="false">${t("profileTabWheel")}</button>
            <button type="button" data-profile-tab="purchases" class="${profileTabButtonClass(false)}" aria-selected="false">${t("profileTabPurchases")}</button>
            <button type="button" data-profile-tab="blackjack" class="${profileTabButtonClass(false)}" aria-selected="false">${t("profileTabBlackjack")}</button>
            <button type="button" data-profile-tab="slot" class="${profileTabButtonClass(false)}" aria-selected="false">${t("profileTabSlot")}</button>
            <button type="button" data-profile-tab="roulette" class="${profileTabButtonClass(false)}" aria-selected="false">${t("profileTabRoulette")}</button>
            <button type="button" data-profile-tab="complaints" class="${profileTabButtonClass(false)}" aria-selected="false">${t("profileTabComplaints")}</button>
          </div>
        </section>

        <section data-profile-panel="info" class="profile-panel p-6">
          <div id="profile-complete-banner" class="hidden mb-6 rounded-xl border border-amber-500/30 bg-amber-500/10 px-4 py-3 text-sm text-amber-100">
            <p class="font-semibold text-amber-50">${t("profileCompleteBannerTitle")}</p>
            <p class="mt-1 text-amber-100/90">${t("profileCompleteBannerHint")}</p>
          </div>
          <div id="profile-password-change-banner" class="hidden mb-6 rounded-xl border border-red-500/30 bg-red-500/10 px-4 py-3 text-sm text-red-100">
            <p class="font-semibold text-red-50">${t("profilePasswordChangeBannerTitle")}</p>
            <p class="mt-1 text-red-100/90">${t("profilePasswordChangeBannerHint")}</p>
          </div>
          <form id="form-profile-password-change" class="hidden mb-6 space-y-4 rounded-2xl border border-red-500/25 bg-red-500/5 p-5">
            <div>
              <h2 class="text-lg font-semibold text-white">${t("profilePasswordChangeTitle")}</h2>
              <p class="mt-1 text-sm text-slate-400">${t("profilePasswordChangeSubtitle")}</p>
            </div>
            <div>
              <label for="profile-password-new" class="mb-1.5 block text-[11px] font-semibold uppercase tracking-wider text-slate-500">${t("authLabelPassword")}</label>
              <input id="profile-password-new" name="newPassword" type="password" autocomplete="new-password" required minlength="8" class="input-site-field w-full text-sm" placeholder="${t("authPlaceholderPassword")}" />
            </div>
            <div>
              <label for="profile-password-new2" class="mb-1.5 block text-[11px] font-semibold uppercase tracking-wider text-slate-500">${t("authLabelPassword2")}</label>
              <input id="profile-password-new2" name="newPassword2" type="password" autocomplete="new-password" required minlength="8" class="input-site-field w-full text-sm" placeholder="${t("authPlaceholderPassword2")}" />
            </div>
            <p id="profile-password-change-error" class="hidden rounded-xl border border-red-500/30 bg-red-950/40 px-3 py-2 text-sm text-red-200" role="alert"></p>
            <button type="submit" class="k-btn k-btn--primary btn-site-primary w-full justify-center py-3 text-sm font-semibold sm:w-auto">${t("profilePasswordChangeSubmit")}</button>
          </form>
          <form id="form-profile-complete" class="hidden mb-6 space-y-4 rounded-2xl border border-accent/25 bg-accent/5 p-5">
            <div>
              <h2 class="text-lg font-semibold text-white">${t("profileCompleteTitle")}</h2>
              <p class="mt-1 text-sm text-slate-400">${t("profileCompleteSubtitle")}</p>
            </div>
            <div>
              <label for="profile-complete-username" class="mb-1.5 block text-[11px] font-semibold uppercase tracking-wider text-slate-500">${t("authLabelUsername")}</label>
              <input id="profile-complete-username" name="username" type="text" autocomplete="username" required minlength="2" maxlength="64" class="input-site-field w-full text-sm" />
            </div>
            <div>
              <label for="profile-complete-email" class="mb-1.5 block text-[11px] font-semibold uppercase tracking-wider text-slate-500">${t("authLabelEmail")}</label>
              <input id="profile-complete-email" name="email" type="email" autocomplete="email" required class="input-site-field w-full text-sm" placeholder="${t("authPlaceholderEmail")}" />
            </div>
            <div>
              <label for="profile-complete-phone" class="mb-1.5 block text-[11px] font-semibold uppercase tracking-wider text-slate-500">${t("authLabelPhone")}</label>
              <input id="profile-complete-phone" name="phone" type="tel" autocomplete="tel" required class="input-site-field w-full text-sm" placeholder="${t("authPlaceholderPhone")}" />
            </div>
            <div>
              <label for="profile-complete-password" class="mb-1.5 block text-[11px] font-semibold uppercase tracking-wider text-slate-500">${t("authLabelPassword")}</label>
              <input id="profile-complete-password" name="password" type="password" autocomplete="new-password" required minlength="8" class="input-site-field w-full text-sm" placeholder="${t("authPlaceholderPassword")}" />
            </div>
            <div>
              <label for="profile-complete-password2" class="mb-1.5 block text-[11px] font-semibold uppercase tracking-wider text-slate-500">${t("authLabelPassword2")}</label>
              <input id="profile-complete-password2" name="password2" type="password" autocomplete="new-password" required minlength="8" class="input-site-field w-full text-sm" placeholder="${t("authPlaceholderPassword2")}" />
            </div>
            <p id="profile-complete-error" class="hidden rounded-xl border border-red-500/30 bg-red-950/40 px-3 py-2 text-sm text-red-200" role="alert"></p>
            <button type="submit" class="k-btn k-btn--primary btn-site-primary w-full justify-center py-3 text-sm font-semibold sm:w-auto">${t("profileCompleteSubmit")}</button>
          </form>
          <h2 class="text-lg font-semibold text-white">${t("profileInfoTitle")}</h2>
          <div class="profile-row mt-4 flex flex-col gap-3 p-4 sm:flex-row sm:items-center sm:justify-between">
            <div class="flex min-w-0 items-start gap-3">
              <span class="flex h-10 w-10 shrink-0 items-center justify-center rounded-xl border border-sky-500/30 bg-gradient-to-b from-sky-500/20 to-sky-600/10 text-sky-200" aria-hidden="true">
                <svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 19l9 2-9-18-9 18 9-2zm0 0v-8"/></svg>
              </span>
              <div class="min-w-0">
                <p class="font-semibold text-white">${t("profileTelegramConnectTitle")}</p>
                <p id="profile-telegram-connect-status" class="mt-1 text-sm profile-muted">${t("profileTelegramConnectHint")}</p>
              </div>
            </div>
            <button type="button" id="profile-go-telegram-invite" class="k-btn k-btn--secondary btn-site-secondary inline-flex w-full shrink-0 items-center justify-center gap-2 rounded-xl px-4 py-2.5 text-sm font-semibold sm:w-auto">
              ${t("profileTelegramConnectCta")}
              <svg class="h-4 w-4 opacity-80" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/></svg>
            </button>
          </div>
          <dl id="profile-user-dl" class="mt-4 grid gap-3 text-sm sm:grid-cols-2"></dl>
          <div id="profile-twofa-card" class="profile-row mt-6 rounded-2xl border border-white/[0.08] bg-[#1a2233]/80 p-5 ring-1 ring-white/[0.05]">
            <div class="flex flex-col gap-2 sm:flex-row sm:items-start sm:justify-between">
              <div>
                <h3 class="text-base font-semibold text-white">${t("profileTwofaTitle")}</h3>
                <p class="mt-1 text-sm text-slate-400">${t("profileTwofaSubtitle")}</p>
                <p id="profile-twofa-status" class="mt-2 text-sm font-medium text-slate-300"></p>
              </div>
              <div id="profile-twofa-actions" class="flex shrink-0 flex-wrap gap-2"></div>
            </div>
            <div id="profile-twofa-setup" class="mt-4 hidden space-y-4 border-t border-white/[0.06] pt-4">
              <img id="profile-twofa-qr" alt="" class="h-[220px] w-[220px] rounded-xl border border-white/10 bg-white p-2" width="220" height="220" />
              <div>
                <p class="text-[11px] font-semibold uppercase tracking-wider text-slate-500">${t("profileTwofaSecretLabel")}</p>
                <code id="profile-twofa-secret" class="mt-1 block break-all rounded-lg bg-black/30 px-3 py-2 text-sm text-emerald-200"></code>
              </div>
              <div>
                <label for="profile-twofa-code" class="mb-1.5 block text-[11px] font-semibold uppercase tracking-wider text-slate-500">${t("profileTwofaCodeLabel")}</label>
                <input id="profile-twofa-code" type="text" inputmode="numeric" autocomplete="one-time-code" class="input-site-field w-full max-w-xs text-sm" />
              </div>
              <p id="profile-twofa-error" class="hidden rounded-xl border border-red-500/30 bg-red-950/40 px-3 py-2 text-sm text-red-200" role="alert"></p>
              <button type="button" id="profile-twofa-confirm" class="k-btn k-btn--primary btn-site-primary inline-flex items-center justify-center rounded-xl px-4 py-2.5 text-sm font-semibold">${t("profileTwofaConfirmBtn")}</button>
            </div>
          </div>
        </section>

        <section data-profile-panel="telegram" class="profile-panel hidden p-6">
          <div id="profile-telegram-invite-mount"></div>
        </section>

        <section data-profile-panel="crypto" class="profile-panel hidden p-6">
          <div class="flex flex-col gap-2 sm:flex-row sm:items-end sm:justify-between">
            <div>
              <h2 class="text-lg font-semibold text-white">${t("profileCryptoTitle")}</h2>
              <p class="mt-1 text-sm text-slate-400">${t("profileCryptoHint")}</p>
            </div>
            <button
              type="submit"
              form="form-crypto-wallets"
              class="k-btn k-btn--primary profile-save-btn inline-flex items-center justify-center rounded-xl px-4 py-2.5 text-sm font-semibold"
            >
              ${t("profileSave")}
            </button>
          </div>
          <form id="form-crypto-wallets" class="mt-6">
            <div class="grid gap-4 sm:grid-cols-2 xl:grid-cols-4">
              ${getCryptoFields().map(cryptoCardHtml).join("")}
            </div>
          </form>
        </section>

        <section data-profile-panel="sponsors" class="profile-panel hidden p-6">
          <div class="flex flex-col gap-2 sm:flex-row sm:items-end sm:justify-between">
            <div>
              <h2 class="text-lg font-semibold text-white">${t("profileSponsorsTitle")}</h2>
              <p class="mt-1 text-sm text-slate-400">${t("profileSponsorsHint")}</p>
            </div>
            <button
              type="submit"
              form="form-sponsor-accounts"
              class="k-btn k-btn--primary profile-save-btn inline-flex items-center justify-center rounded-xl px-4 py-2.5 text-sm font-semibold"
            >
              ${t("profileSave")}
            </button>
          </div>
          <form id="form-sponsor-accounts" class="mt-6">
            <div id="profile-sponsor-accounts-grid" class="grid gap-4 sm:grid-cols-2"></div>
          </form>
        </section>

        <section data-profile-panel="wheel" class="profile-panel hidden p-6">
          <h2 class="text-lg font-semibold text-white">${t("profileWheelTitle")}</h2>
          <div id="profile-wheel-history" class="mt-4 space-y-3 text-sm"></div>
        </section>

        <section data-profile-panel="purchases" class="profile-panel hidden p-6">
          <h2 class="text-lg font-semibold text-white">${t("profilePurchasesTitle")}</h2>
          <div id="profile-purchases" class="mt-4 space-y-3 text-sm"></div>
        </section>

        <section data-profile-panel="blackjack" class="profile-panel hidden p-6">
          <div class="flex flex-col gap-2 sm:flex-row sm:items-start sm:justify-between">
            <div>
              <h2 class="text-lg font-semibold text-white">${t("profileBjTitle")}</h2>
            </div>
            <p id="profile-blackjack-maxbet" class="shrink-0 rounded-xl border border-sky-500/25 bg-sky-500/10 px-3 py-2 text-sm font-medium text-sky-100"></p>
          </div>
          <div class="mt-4">
            <div id="profile-blackjack-pager" class="mb-3 hidden flex flex-wrap items-center justify-end gap-3 border-b border-white/[0.06] pb-3">
              <div class="flex items-center gap-1">
                <button
                  type="button"
                  id="profile-bj-prev"
                  class="k-btn k-btn--icon k-btn--ghost profile-pager-btn inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-lg disabled:cursor-not-allowed disabled:opacity-30"
                  aria-label="${t("profilePrevPage")}"
                >
                  <svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"/></svg>
                </button>
                <span id="profile-bj-page-label" class="min-w-[7rem] text-center text-sm font-medium tabular-nums text-slate-300"></span>
                <button
                  type="button"
                  id="profile-bj-next"
                  class="k-btn k-btn--icon k-btn--ghost profile-pager-btn inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-lg disabled:cursor-not-allowed disabled:opacity-30"
                  aria-label="${t("profileNextPage")}"
                >
                  <svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/></svg>
                </button>
              </div>
            </div>
            <div id="profile-blackjack-history" class="space-y-3 text-sm"></div>
          </div>
        </section>

        <section data-profile-panel="slot" class="profile-panel hidden p-6">
          <div class="flex flex-col gap-2 sm:flex-row sm:items-start sm:justify-between">
            <div>
              <h2 class="text-lg font-semibold text-white">${t("profileSlotTitle")}</h2>
            </div>
            <p id="profile-slot-maxbet" class="shrink-0 rounded-xl border border-fuchsia-500/25 bg-fuchsia-500/10 px-3 py-2 text-sm font-medium text-fuchsia-100"></p>
          </div>
          <div class="mt-4">
            <div id="profile-slot-pager" class="mb-3 hidden flex flex-wrap items-center justify-end gap-3 border-b border-white/[0.06] pb-3">
              <div class="flex items-center gap-1">
                <button
                  type="button"
                  id="profile-slot-prev"
                  class="k-btn k-btn--icon k-btn--ghost profile-pager-btn inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-lg disabled:cursor-not-allowed disabled:opacity-30"
                  aria-label="${t("profilePrevPage")}"
                >
                  <svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"/></svg>
                </button>
                <span id="profile-slot-page-label" class="min-w-[7rem] text-center text-sm font-medium tabular-nums text-slate-300"></span>
                <button
                  type="button"
                  id="profile-slot-next"
                  class="k-btn k-btn--icon k-btn--ghost profile-pager-btn inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-lg disabled:cursor-not-allowed disabled:opacity-30"
                  aria-label="${t("profileNextPage")}"
                >
                  <svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/></svg>
                </button>
              </div>
            </div>
            <div id="profile-slot-history" class="space-y-3 text-sm"></div>
          </div>
        </section>

        <section data-profile-panel="roulette" class="profile-panel hidden p-6">
          <div class="flex flex-col gap-2 sm:flex-row sm:items-start sm:justify-between">
            <div>
              <h2 class="text-lg font-semibold text-white">${t("profileRouletteTitle")}</h2>
            </div>
            <p id="profile-roulette-maxbet" class="shrink-0 rounded-xl border border-sky-500/25 bg-sky-500/10 px-3 py-2 text-sm font-medium text-sky-100"></p>
          </div>
          <div class="mt-4">
            <div id="profile-roulette-pager" class="mb-3 hidden flex flex-wrap items-center justify-end gap-3 border-b border-white/[0.06] pb-3">
              <div class="flex items-center gap-1">
                <button
                  type="button"
                  id="profile-roulette-prev"
                  class="k-btn k-btn--icon k-btn--ghost profile-pager-btn inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-lg disabled:cursor-not-allowed disabled:opacity-30"
                  aria-label="${t("profilePrevPage")}"
                >
                  <svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"/></svg>
                </button>
                <span id="profile-roulette-page-label" class="min-w-[7rem] text-center text-sm font-medium tabular-nums text-slate-300"></span>
                <button
                  type="button"
                  id="profile-roulette-next"
                  class="k-btn k-btn--icon k-btn--ghost profile-pager-btn inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-lg disabled:cursor-not-allowed disabled:opacity-30"
                  aria-label="${t("profileNextPage")}"
                >
                  <svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/></svg>
                </button>
              </div>
            </div>
            <div id="profile-roulette-history" class="space-y-3 text-sm"></div>
          </div>
        </section>

        <section data-profile-panel="complaints" class="profile-panel hidden p-6">
          <h2 class="text-lg font-semibold text-white">${t("profileComplaintsTitle")}</h2>
          <div id="profile-complaints" class="mt-4 space-y-3 text-sm"></div>
        </section>

        <div class="mt-8 border-t border-white/10 pt-6">
          <button
            type="button"
            id="profile-logout-btn"
            class="k-btn k-btn--danger profile-logout-btn flex w-full items-center justify-center gap-2 rounded-xl border border-accent/35 bg-accent/[0.14] py-3.5 text-sm font-semibold text-slate-100 shadow-[inset_0_1px_0_rgba(255,255,255,0.08),0_4px_24px_-12px_rgba(166,124,50,0.22)] transition hover:border-accent-bright/55 hover:bg-accent/25 hover:text-white focus:outline-none focus:ring-2 focus:ring-accent-bright/35 active:scale-[0.99] sm:py-4 sm:text-base"
          >
            <svg class="h-5 w-5 shrink-0 opacity-95" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1"/></svg>
            ${t("profileLogout")}
          </button>
        </div>
      </div>
    </section>
  `;

  const loadingGate = root.querySelector("#profile-loading-gate");
  const gate = root.querySelector("#profile-auth-gate");
  const content = root.querySelector("#profile-content");
  const dl = root.querySelector("#profile-user-dl");
  const purchasesEl = root.querySelector("#profile-purchases");
  const complaintsEl = root.querySelector("#profile-complaints");
  const wheelHistoryEl = root.querySelector("#profile-wheel-history");
  const blackjackHistoryEl = root.querySelector("#profile-blackjack-history");
  const blackjackMaxBetEl = root.querySelector("#profile-blackjack-maxbet");
  const blackjackPagerEl = root.querySelector("#profile-blackjack-pager");
  const blackjackPrevBtn = root.querySelector("#profile-bj-prev");
  const blackjackNextBtn = root.querySelector("#profile-bj-next");
  const blackjackPageLabelEl = root.querySelector("#profile-bj-page-label");
  const slotHistoryEl = root.querySelector("#profile-slot-history");
  const slotMaxBetEl = root.querySelector("#profile-slot-maxbet");
  const slotPagerEl = root.querySelector("#profile-slot-pager");
  const slotPrevBtn = root.querySelector("#profile-slot-prev");
  const slotNextBtn = root.querySelector("#profile-slot-next");
  const slotPageLabelEl = root.querySelector("#profile-slot-page-label");
  const rouletteHistoryEl = root.querySelector("#profile-roulette-history");
  const rouletteMaxBetEl = root.querySelector("#profile-roulette-maxbet");
  const roulettePagerEl = root.querySelector("#profile-roulette-pager");
  const roulettePrevBtn = root.querySelector("#profile-roulette-prev");
  const rouletteNextBtn = root.querySelector("#profile-roulette-next");
  const roulettePageLabelEl = root.querySelector("#profile-roulette-page-label");

  let bjAllRounds = [];
  let bjPageIndex = 0;
  const BJ_PER_PAGE = 10;

  let slotAllRounds = [];
  let slotPageIndex = 0;
  const SLOT_PER_PAGE = 10;

  let rouletteAllRounds = [];
  let roulettePageIndex = 0;
  const ROULETTE_PER_PAGE = 10;

  function paintBlackjackHistory() {
    if (!blackjackHistoryEl) return;
    const total = bjAllRounds.length;
    if (!total) {
      blackjackHistoryEl.innerHTML = `<p class="text-slate-400">${t("profileEmptyBj")}</p>`;
      blackjackPagerEl?.classList.add("hidden");
      return;
    }
    const totalPages = Math.max(1, Math.ceil(total / BJ_PER_PAGE));
    if (bjPageIndex >= totalPages) bjPageIndex = totalPages - 1;
    if (bjPageIndex < 0) bjPageIndex = 0;
    const start = bjPageIndex * BJ_PER_PAGE;
    const slice = bjAllRounds.slice(start, start + BJ_PER_PAGE);
    blackjackHistoryEl.innerHTML = slice.map((r) => blackjackRoundCardHtml(r)).join("");
    if (blackjackPagerEl && blackjackPageLabelEl) {
      blackjackPagerEl.classList.toggle("hidden", totalPages <= 1);
      blackjackPageLabelEl.textContent = t("profilePageLabel")
        .replace("{cur}", String(bjPageIndex + 1))
        .replace("{total}", String(totalPages));
    }
    if (blackjackPrevBtn) blackjackPrevBtn.disabled = bjPageIndex <= 0;
    if (blackjackNextBtn) blackjackNextBtn.disabled = bjPageIndex >= totalPages - 1;
  }

  blackjackPrevBtn?.addEventListener("click", () => {
    if (bjPageIndex > 0) {
      bjPageIndex -= 1;
      paintBlackjackHistory();
    }
  });
  blackjackNextBtn?.addEventListener("click", () => {
    const totalPages = Math.max(1, Math.ceil(bjAllRounds.length / BJ_PER_PAGE));
    if (bjPageIndex < totalPages - 1) {
      bjPageIndex += 1;
      paintBlackjackHistory();
    }
  });

  function paintSlotHistory() {
    if (!slotHistoryEl) return;
    const total = slotAllRounds.length;
    if (!total) {
      slotHistoryEl.innerHTML = `<p class="text-slate-400">${t("profileEmptySlot")}</p>`;
      slotPagerEl?.classList.add("hidden");
      return;
    }
    const totalPages = Math.max(1, Math.ceil(total / SLOT_PER_PAGE));
    if (slotPageIndex >= totalPages) slotPageIndex = totalPages - 1;
    if (slotPageIndex < 0) slotPageIndex = 0;
    const start = slotPageIndex * SLOT_PER_PAGE;
    const slice = slotAllRounds.slice(start, start + SLOT_PER_PAGE);
    slotHistoryEl.innerHTML = slice.map((r) => slotRoundCardHtml(r)).join("");
    if (slotPagerEl && slotPageLabelEl) {
      slotPagerEl.classList.toggle("hidden", totalPages <= 1);
      slotPageLabelEl.textContent = t("profilePageLabel")
        .replace("{cur}", String(slotPageIndex + 1))
        .replace("{total}", String(totalPages));
    }
    if (slotPrevBtn) slotPrevBtn.disabled = slotPageIndex <= 0;
    if (slotNextBtn) slotNextBtn.disabled = slotPageIndex >= totalPages - 1;
  }

  slotPrevBtn?.addEventListener("click", () => {
    if (slotPageIndex > 0) {
      slotPageIndex -= 1;
      paintSlotHistory();
    }
  });
  slotNextBtn?.addEventListener("click", () => {
    const totalPages = Math.max(1, Math.ceil(slotAllRounds.length / SLOT_PER_PAGE));
    if (slotPageIndex < totalPages - 1) {
      slotPageIndex += 1;
      paintSlotHistory();
    }
  });

  function paintRouletteHistory() {
    if (!rouletteHistoryEl) return;
    const total = rouletteAllRounds.length;
    if (!total) {
      rouletteHistoryEl.innerHTML = `<p class="text-slate-400">${t("profileEmptyRoulette")}</p>`;
      roulettePagerEl?.classList.add("hidden");
      return;
    }
    const totalPages = Math.max(1, Math.ceil(total / ROULETTE_PER_PAGE));
    if (roulettePageIndex >= totalPages) roulettePageIndex = totalPages - 1;
    if (roulettePageIndex < 0) roulettePageIndex = 0;
    const start = roulettePageIndex * ROULETTE_PER_PAGE;
    const slice = rouletteAllRounds.slice(start, start + ROULETTE_PER_PAGE);
    rouletteHistoryEl.innerHTML = slice.map((r) => rouletteRoundCardHtml(r)).join("");
    if (roulettePagerEl && roulettePageLabelEl) {
      roulettePagerEl.classList.toggle("hidden", totalPages <= 1);
      roulettePageLabelEl.textContent = t("profilePageLabel")
        .replace("{cur}", String(roulettePageIndex + 1))
        .replace("{total}", String(totalPages));
    }
    if (roulettePrevBtn) roulettePrevBtn.disabled = roulettePageIndex <= 0;
    if (rouletteNextBtn) rouletteNextBtn.disabled = roulettePageIndex >= totalPages - 1;
  }

  roulettePrevBtn?.addEventListener("click", () => {
    if (roulettePageIndex > 0) {
      roulettePageIndex -= 1;
      paintRouletteHistory();
    }
  });
  rouletteNextBtn?.addEventListener("click", () => {
    const totalPages = Math.max(1, Math.ceil(rouletteAllRounds.length / ROULETTE_PER_PAGE));
    if (roulettePageIndex < totalPages - 1) {
      roulettePageIndex += 1;
      paintRouletteHistory();
    }
  });

  const formCrypto = root.querySelector("#form-crypto-wallets");
  const formSponsorAccounts = root.querySelector("#form-sponsor-accounts");
  const sponsorGrid = root.querySelector("#profile-sponsor-accounts-grid");

  root.querySelector("#profile-logout-btn")?.addEventListener("click", async () => {
    await postLogout();
    await globalThis.__siteRefreshUser?.();
    showToast(t("profileLogoutToast"), "info");
    const go = globalThis.__siteNavigateTo;
    if (typeof go === "function") go("/");
    else window.location.hash = "#/";
  });

  const tgMount = root.querySelector("#profile-telegram-invite-mount");
  let telegramInviteMounted = false;

  async function ensureTelegramInvitePanel() {
    if (!tgMount || telegramInviteMounted) return;
    telegramInviteMounted = true;
    await mountProfileTelegramInvite(tgMount);
  }

  function goToTelegramInviteTab() {
    if (!content) return;
    setActiveProfileTab(content, "telegram");
    void ensureTelegramInvitePanel();
    const panel = content.querySelector('[data-profile-panel="telegram"]');
    panel?.scrollIntoView({ behavior: "smooth", block: "start" });
  }

  root.querySelector("#profile-go-telegram-invite")?.addEventListener("click", () => {
    goToTelegramInviteTab();
  });

  content?.addEventListener("click", (e) => {
    const tabBtn = e.target.closest("[data-profile-tab]");
    if (tabBtn) {
      const tab = String(tabBtn.getAttribute("data-profile-tab") || "info");
      setActiveProfileTab(content, tab);
      if (tab === "telegram") void ensureTelegramInvitePanel();
    }
  });

  (async () => {
    const [data, sponsors] = await Promise.all([fetchUserProfile(), loadSponsorsForProfile()]);
    if (!data) {
      loadingGate?.classList.add("hidden");
      updateProfileHero(root, null, null);
      notifyApiFailure();
      return;
    }
    if (data.ok === false) {
      if (data.error === "auth") {
        loadingGate?.classList.add("hidden");
        updateProfileHero(root, null, null);
        gate.classList.remove("hidden");
        content.classList.add("hidden");
        return;
      }
      if (data.error === "db") {
        loadingGate?.classList.add("hidden");
        notifyDbFailure();
        gate.classList.remove("hidden");
        content.classList.add("hidden");
        return;
      }
      loadingGate?.classList.add("hidden");
      notifyApiFailure();
      return;
    }

    loadingGate?.classList.add("hidden");
    gate.classList.add("hidden");
    content.classList.remove("hidden");

    const pendingTab = sessionStorage.getItem("site_profile_tab");
    const forceComplete = sessionStorage.getItem("site_profile_complete") === "1";
    const forcePasswordChange = sessionStorage.getItem("site_password_change") === "1";
    const needsProfileCompletion = !!data.needsProfileCompletion;
    const needsPasswordChange = !!data.needsPasswordChange;
    const initialTab =
      needsPasswordChange || needsProfileCompletion
        ? "info"
        : pendingTab === "telegram" && PROFILE_TABS.includes("telegram")
          ? "telegram"
          : "info";
    if (pendingTab) sessionStorage.removeItem("site_profile_tab");
    if (forceComplete) sessionStorage.removeItem("site_profile_complete");
    if (forcePasswordChange) sessionStorage.removeItem("site_password_change");
    setActiveProfileTab(content, initialTab);
    if (initialTab === "telegram") void ensureTelegramInvitePanel();

    const u = data.user;
    const level = data.level && typeof data.level === "object" ? data.level : {};
    updateProfileHero(root, u, level);

    const tgStatusEl = root.querySelector("#profile-telegram-connect-status");
    const tg = data.telegram && typeof data.telegram === "object" ? data.telegram : {};
    if (tgStatusEl) {
      if (tg.verified && tg.username) {
        tgStatusEl.textContent = t("tgInviteTelegramOk").replace("{user}", `@${tg.username}`);
      } else if (tg.verified) {
        tgStatusEl.textContent = t("profileTelegramConnectHintLinked");
      } else {
        tgStatusEl.textContent = t("profileTelegramConnectHint");
      }
    }
    const completeBanner = root.querySelector("#profile-complete-banner");
    const completeForm = root.querySelector("#form-profile-complete");
    const passwordBanner = root.querySelector("#profile-password-change-banner");
    const passwordForm = root.querySelector("#form-profile-password-change");
    root.querySelector("#profile-twofa-card")?.classList.toggle("hidden", needsPasswordChange || needsProfileCompletion);

    if (needsPasswordChange) {
      passwordBanner?.classList.remove("hidden");
      passwordForm?.classList.remove("hidden");
      completeBanner?.classList.add("hidden");
      completeForm?.classList.add("hidden");
      content.querySelectorAll("[data-profile-tab]").forEach((btn) => {
        if (btn.getAttribute("data-profile-tab") !== "info") {
          btn.setAttribute("disabled", "disabled");
          btn.classList.add("opacity-40", "pointer-events-none");
        }
      });
      if (forcePasswordChange) showToast(t("profilePasswordChangeRequiredToast"), "info");
    } else if (needsProfileCompletion) {
      completeBanner?.classList.remove("hidden");
      completeForm?.classList.remove("hidden");
      content.querySelectorAll("[data-profile-tab]").forEach((btn) => {
        if (btn.getAttribute("data-profile-tab") !== "info") {
          btn.setAttribute("disabled", "disabled");
          btn.classList.add("opacity-40", "pointer-events-none");
        }
      });
      const usernameInput = root.querySelector("#profile-complete-username");
      const emailInput = root.querySelector("#profile-complete-email");
      const phoneInput = root.querySelector("#profile-complete-phone");
      if (usernameInput instanceof HTMLInputElement) usernameInput.value = u.username || "";
      if (emailInput instanceof HTMLInputElement) emailInput.value = u.email || "";
      if (phoneInput instanceof HTMLInputElement) phoneInput.value = u.phone || "";
      if (forceComplete) showToast(t("profileCompleteRequiredToast"), "info");
    }

    dl.innerHTML = `
      <div class="profile-dl-cell px-3 py-2">
        <dt class="text-xs uppercase tracking-wide text-slate-500">${t("profileDlUsername")}</dt>
        <dd class="mt-1 font-medium text-white">${escapeHtml(u.username)}</dd>
      </div>
      <div class="profile-dl-cell px-3 py-2">
        <dt class="text-xs uppercase tracking-wide text-slate-500">${t("profileDlEmail")}</dt>
        <dd class="mt-1 font-medium text-white">${u.email ? escapeHtml(u.email) : "—"}</dd>
      </div>
      <div class="profile-dl-cell px-3 py-2">
        <dt class="text-xs uppercase tracking-wide text-slate-500">${t("profileDlPhone")}</dt>
        <dd class="mt-1 font-medium text-white">${u.phone ? escapeHtml(u.phone) : "—"}</dd>
      </div>
      <div class="profile-dl-cell px-3 py-2">
        <dt class="text-xs uppercase tracking-wide text-slate-500">${t("profileDlSpent")}</dt>
        <dd class="mt-1 font-medium text-sky-200/95">${formatCoins(u.totalSpent)}</dd>
      </div>
      <div class="profile-dl-cell px-3 py-2">
        <dt class="text-xs uppercase tracking-wide text-slate-500">${t("profileDlRegistered")}</dt>
        <dd class="mt-1 font-medium text-white">${formatTs(u.createdAt)}</dd>
      </div>
    `;

    initProfileTwofa(root, data.twofa || {});

    const crypto = data.crypto || {};
    for (const f of CRYPTO_FIELD_DEFS) {
      const inp = formCrypto?.querySelector(`[name="${f.key}"]`);
      if (inp) inp.value = crypto[f.key] || "";
    }

    const savedSponsorAccounts = Array.isArray(data.sponsorAccounts) ? data.sponsorAccounts : [];
    const sponsorValueMap = new Map(savedSponsorAccounts.map((x) => [String(x.sponsorId || ""), String(x.accountValue || "")]));
    if (Array.isArray(sponsors) && sponsors.length) {
      sponsorGrid.innerHTML = sponsors
        .map((s) => sponsorAccountRowHtml(s, sponsorValueMap.get(String(s.id || "")) || ""))
        .join("");
    } else {
      sponsorGrid.innerHTML = `<p class="text-sm text-slate-400">${t("profileSponsorsLoadFail")}</p>`;
    }

    const purchases = Array.isArray(data.purchases) ? data.purchases : [];
    if (!purchases.length) {
      purchasesEl.innerHTML = `<p class="text-slate-400">${t("profileNoPurchases")}</p>`;
    } else {
      purchasesEl.innerHTML = purchases
        .map((p) => {
          const status = String(p.status || "pending");
          const statusBadge =
            status === "approved"
              ? `<span class="inline-flex items-center rounded-md border border-sky-500/35 bg-sky-500/15 px-2 py-0.5 text-xs font-semibold text-sky-200">${t("profilePurchaseApproved")}</span>`
              : status === "rejected"
                ? `<span class="inline-flex items-center rounded-md border border-rose-500/35 bg-rose-500/15 px-2 py-0.5 text-xs font-semibold text-rose-200">${t("profilePurchaseRejected")}</span>`
                : `<span class="inline-flex items-center rounded-md border border-sky-500/35 bg-sky-500/15 px-2 py-0.5 text-xs font-semibold text-sky-200">${t("profilePurchasePending")}</span>`;
          return `
        <div class="profile-row flex flex-col gap-2 px-4 py-3 sm:flex-row sm:items-center sm:justify-between">
          <div>
            <p class="font-medium text-white">${escapeHtml(p.itemTitle)}</p>
            <p class="text-xs text-slate-500">${formatTs(p.createdAt)}</p>
            <div class="mt-1">${statusBadge}</div>
          </div>
          <div class="text-sm font-semibold text-sky-200/95">${formatCoins(p.price)}</div>
        </div>
      `;
        })
        .join("");
    }

    const bj = data.blackjack && typeof data.blackjack === "object" ? data.blackjack : {};
    const bjMax = Number(bj.maxBet) || 0;
    if (blackjackMaxBetEl) {
      blackjackMaxBetEl.textContent =
        bjMax > 0 ? t("profileBjMaxBet").replace("{n}", String(bjMax)) : t("profileBjNoRecord");
    }
    const blackjackRounds = Array.isArray(bj.rounds) ? bj.rounds : [];
    bjAllRounds = blackjackRounds;
    bjPageIndex = 0;
    paintBlackjackHistory();

    const sl = data.slot && typeof data.slot === "object" ? data.slot : {};
    const slMax = Number(sl.maxBet) || 0;
    if (slotMaxBetEl) {
      slotMaxBetEl.textContent =
        slMax > 0 ? t("profileSlotMaxBet").replace("{n}", String(slMax)) : t("profileSlotNoRecord");
    }
    const slotRounds = Array.isArray(sl.rounds) ? sl.rounds : [];
    slotAllRounds = slotRounds;
    slotPageIndex = 0;
    paintSlotHistory();

    const rl = data.roulette && typeof data.roulette === "object" ? data.roulette : {};
    const rlMax = Number(rl.maxBet) || 0;
    if (rouletteMaxBetEl) {
      rouletteMaxBetEl.textContent =
        rlMax > 0 ? t("profileRouletteMaxBet").replace("{n}", String(rlMax)) : t("profileRouletteNoRecord");
    }
    const rouletteRounds = Array.isArray(rl.rounds) ? rl.rounds : [];
    rouletteAllRounds = rouletteRounds;
    roulettePageIndex = 0;
    paintRouletteHistory();

    const wheelHistory = Array.isArray(data.wheelHistory) ? data.wheelHistory : [];
    if (!wheelHistory.length) {
      wheelHistoryEl.innerHTML = `<p class="text-slate-400">${t("profileWheelEmpty")}</p>`;
    } else {
      wheelHistoryEl.innerHTML = wheelHistory
        .map((w) => {
          const amount = Number(w.amount) || 0;
          const segment = Number(w.segment);
          const prizeLine =
            amount <= 0 ? t("profileWheelPass") : t("profileWheelPrize").replace("{amount}", String(amount));
          return `
        <div class="profile-row flex flex-col gap-2 px-4 py-3 sm:flex-row sm:items-center sm:justify-between">
          <div>
            <p class="font-medium text-white">${prizeLine}</p>
            <p class="text-xs text-slate-500">${t("profileWheelSegment")} ${Number.isFinite(segment) ? segment + 1 : "—"} · ${formatTs(w.createdAt)}</p>
          </div>
          <span class="inline-flex items-center rounded-md border border-accent/35 bg-accent/15 px-2 py-0.5 text-xs font-semibold text-accent-bright">${t("profileWheelBadge")}</span>
        </div>
      `;
        })
        .join("");
    }

    const complaints = Array.isArray(data.complaints) ? data.complaints : [];
    if (!complaints.length) {
      complaintsEl.innerHTML = `<p class="text-slate-400">${t("profileComplaintsEmpty")}</p>`;
    } else {
      complaintsEl.innerHTML = complaints
        .map((c) => {
          const status = String(c.status || "pending");
          const category = String(c.category || "other");
          const statusBadge =
            status === "approved"
              ? `<span class="inline-flex items-center rounded-md border border-sky-500/35 bg-sky-500/15 px-2 py-0.5 text-xs font-semibold text-sky-200">${t("profilePurchaseApproved")}</span>`
              : status === "rejected"
                ? `<span class="inline-flex items-center rounded-md border border-rose-500/35 bg-rose-500/15 px-2 py-0.5 text-xs font-semibold text-rose-200">${t("profilePurchaseRejected")}</span>`
                : `<span class="inline-flex items-center rounded-md border border-sky-500/35 bg-sky-500/15 px-2 py-0.5 text-xs font-semibold text-sky-200">${t("profilePurchasePending")}</span>`;
          const categoryBadge =
            category === "sponsor"
              ? `<span class="inline-flex items-center rounded-md border border-accent-muted/40 bg-accent-muted/15 px-2 py-0.5 text-xs font-semibold text-accent-bright">${t("profileComplaintSponsor")}</span>`
              : `<span class="inline-flex items-center rounded-md border border-violet-500/35 bg-violet-500/15 px-2 py-0.5 text-xs font-semibold text-violet-200">${t("profileComplaintOther")}</span>`;
          const sponsorLine =
            category === "sponsor"
              ? `<p class="text-xs text-slate-500">${t("profileComplaintSponsorLine")} <span class="text-slate-300">${escapeHtml(c.sponsorTitle || c.sponsorId || "—")}</span></p>`
              : "";
          return `
        <div class="profile-row px-4 py-3">
          <div class="mb-2 flex flex-wrap items-center gap-2">
            ${categoryBadge}
            ${statusBadge}
            <span class="text-xs text-slate-500">${formatTs(c.createdAt)}</span>
          </div>
          ${sponsorLine}
          <p class="mt-1 whitespace-pre-wrap text-sm leading-relaxed text-slate-200">${escapeHtml(c.message || "")}</p>
        </div>`;
        })
        .join("");
    }

    const formProfilePasswordChange = root.querySelector("#form-profile-password-change");
    formProfilePasswordChange?.addEventListener("submit", async (e) => {
      e.preventDefault();
      const errEl = root.querySelector("#profile-password-change-error");
      const showPwErr = (msg) => {
        if (!errEl) return;
        if (!msg) {
          errEl.classList.add("hidden");
          errEl.textContent = "";
          return;
        }
        errEl.textContent = msg;
        errEl.classList.remove("hidden");
      };
      showPwErr("");
      const newPassword = root.querySelector("#profile-password-new")?.value || "";
      const newPassword2 = root.querySelector("#profile-password-new2")?.value || "";
      if (newPassword.length < 8) {
        showPwErr(t("authErrPasswordShort"));
        return;
      }
      if (newPassword !== newPassword2) {
        showPwErr(t("authErrPasswordMismatch"));
        return;
      }
      const res = await postPasswordChange({ newPassword, newPassword2 });
      if (!res.ok) {
        if (res.data?.error === "password") showPwErr(t("authErrPasswordShort"));
        else if (res.data?.error === "mismatch") showPwErr(t("authErrPasswordMismatch"));
        else if (res.data?.error === "db") notifyDbFailure();
        else showPwErr(t("authErrPasswordChangeFail"));
        return;
      }
      showToast(t("profilePasswordChangeSuccess"), "success");
      await globalThis.__siteRefreshUser?.();
      await renderProfile(root);
    });

    const formProfileComplete = root.querySelector("#form-profile-complete");
    formProfileComplete?.addEventListener("submit", async (e) => {
      e.preventDefault();
      const errEl = root.querySelector("#profile-complete-error");
      const showCompleteErr = (msg) => {
        if (!errEl) return;
        if (!msg) {
          errEl.classList.add("hidden");
          errEl.textContent = "";
          return;
        }
        errEl.textContent = msg;
        errEl.classList.remove("hidden");
      };
      showCompleteErr("");
      const username = root.querySelector("#profile-complete-username")?.value?.trim() || "";
      const email = root.querySelector("#profile-complete-email")?.value?.trim() || "";
      const phone = root.querySelector("#profile-complete-phone")?.value?.trim() || "";
      const password = root.querySelector("#profile-complete-password")?.value || "";
      const password2 = root.querySelector("#profile-complete-password2")?.value || "";
      if (username.length < 2) {
        showCompleteErr(t("authErrUsernameShort"));
        return;
      }
      if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
        showCompleteErr(t("authErrEmailInvalid"));
        return;
      }
      if (String(phone).replace(/\D/g, "").length < 10) {
        showCompleteErr(t("authErrPhoneInvalid"));
        return;
      }
      if (password.length < 8) {
        showCompleteErr(t("authErrPasswordShort"));
        return;
      }
      if (password !== password2) {
        showCompleteErr(t("authErrPasswordMismatch"));
        return;
      }
      const res = await postProfileComplete({ username, email, phone, password });
      if (!res.ok) {
        if (res.status === 409 || res.data?.error === "taken") {
          showCompleteErr(t("authErrTaken"));
          return;
        }
        if (res.data?.error === "email") showCompleteErr(t("authErrEmailInvalid"));
        else if (res.data?.error === "phone") showCompleteErr(t("authErrPhoneInvalid"));
        else if (res.data?.error === "password") showCompleteErr(t("authErrPasswordShort"));
        else if (res.data?.error === "username") showCompleteErr(t("authErrUsernameRules"));
        else if (res.data?.error === "db") notifyDbFailure();
        else notifyApiFailure();
        return;
      }
      showToast(t("profileCompleteSuccess"), "success");
      await globalThis.__siteRefreshUser?.();
      await renderProfile(root);
    });

    formCrypto?.addEventListener("submit", async (e) => {
      e.preventDefault();
      const body = {};
      for (const f of CRYPTO_FIELD_DEFS) {
        const inp = formCrypto.querySelector(`[name="${f.key}"]`);
        body[f.key] = inp ? String(inp.value || "").trim() : "";
      }
      const res = await postUserCrypto(body);
      if (!res || !res.ok) {
        if (res?.status === 401) showToast(t("profileToastSession"), "error");
        else if (res?.data?.error === "db") notifyDbFailure();
        else notifyApiFailure();
        return;
      }
      const saved = res.data?.crypto;
      if (saved && typeof saved === "object") {
        for (const f of CRYPTO_FIELD_DEFS) {
          const inp = formCrypto.querySelector(`[name="${f.key}"]`);
          if (inp) inp.value = saved[f.key] != null ? String(saved[f.key]) : "";
        }
      }
      showToast(t("profileCryptoSaved"), "success");
    });

    formSponsorAccounts?.addEventListener("submit", async (e) => {
      e.preventDefault();
      const inputs = [...formSponsorAccounts.querySelectorAll("input[data-sponsor-id]")];
      const entries = inputs
        .map((inp) => ({
          sponsorId: String(inp.getAttribute("data-sponsor-id") || "").trim(),
          sponsorTitle: String(inp.getAttribute("data-sponsor-title") || "").trim(),
          accountValue: String(inp.value || "").trim(),
        }))
        .filter((x) => x.sponsorId !== "");
      const res = await postUserSponsorAccounts(entries);
      if (!res || !res.ok) {
        if (res?.status === 401) showToast(t("profileToastSession"), "error");
        else if (res?.data?.error === "db") notifyDbFailure();
        else notifyApiFailure();
        return;
      }
      const saved = Array.isArray(res.data?.sponsorAccounts) ? res.data.sponsorAccounts : [];
      const map = new Map(saved.map((x) => [String(x.sponsorId || ""), String(x.accountValue || "")]));
      inputs.forEach((inp) => {
        const sid = String(inp.getAttribute("data-sponsor-id") || "");
        inp.value = map.get(sid) || "";
      });
      showToast(t("profileSponsorSaved"), "success");
    });
  })();
}

function escapeHtml(s) {
  return String(s ?? "")
    .replace(/&/g, "&amp;")
    .replace(/</g, "&lt;")
    .replace(/>/g, "&gt;")
    .replace(/"/g, "&quot;");
}

function formatCoins(n) {
  const x = Number(n);
  if (!Number.isFinite(x)) return "—";
  return `${x} ${t("marketCoinWord")}`;
}

function formatTs(ts) {
  if (ts == null || ts === "") return "—";
  try {
    const sec = Number(ts);
    if (!Number.isFinite(sec)) return "—";
    const loc = getSiteLocale() === "en" ? "en-US" : "tr-TR";
    return new Date(sec * 1000).toLocaleString(loc, {
      dateStyle: "short",
      timeStyle: "short",
    });
  } catch {
    return "—";
  }
}
