import { escapeHtml } from "../utils/escape-html.js";
import { showToast } from "../components/toast.js";
import { fetchSessionUser, postMarketPurchase, apiUrl } from "../auth/session.js";
import { t, getSiteLocale } from "../config/site.js";

let marketItems = [];
let marketPollTimer = null;
let marketPollAbort = null;
let marketOutlet = null;
let marketUser = null;
let marketVisibilityHandler = null;

const MARKET_POLL_MS = 8000;

function formatCoinsDisplay(n) {
  const x = Number(n);
  if (!Number.isFinite(x)) return "0";
  const loc = getSiteLocale() === "en" ? "en-US" : "tr-TR";
  return x.toLocaleString(loc, { maximumFractionDigits: 0 });
}

function itemStock(item) {
  const s = Number(item?.stock);
  return Number.isFinite(s) ? Math.max(0, Math.floor(s)) : 0;
}

function normalizeMarketItems(raw) {
  if (!Array.isArray(raw)) return [];
  return raw.map((row) => ({
    ...row,
    stock: itemStock(row),
  }));
}

function marketStockSignature(items) {
  return items.map((i) => `${i.id}:${itemStock(i)}`).join("|");
}

function stockBadgeHtml(stock) {
  if (stock > 0) {
    return `<span class="mt-2 inline-flex items-center rounded-md bg-accent/[0.08] px-2 py-0.5 text-[11px] font-semibold uppercase tracking-wide text-accent ring-1 ring-accent/20">${escapeHtml(t("marketStockLabel"))}: <span class="ml-1 tabular-nums">${formatCoinsDisplay(stock)}</span></span>`;
  }
  return `<span class="mt-2 inline-flex items-center rounded-md bg-white/[0.04] px-2 py-0.5 text-[11px] font-semibold uppercase tracking-wide text-slate-500 ring-1 ring-white/[0.06]">${escapeHtml(t("marketStockOut"))}</span>`;
}

async function loadMarketJson() {
  const ts = Date.now();
  const signal = marketPollAbort?.signal;

  try {
    const r = await fetch(apiUrl(`market.php?t=${ts}`), { cache: "no-store", signal });
    const data = await r.json().catch(() => ({}));
    if (r.ok && data.ok === true && Array.isArray(data.items)) {
      marketItems = normalizeMarketItems(data.items);
      return;
    }
  } catch (e) {
    if (e?.name === "AbortError") throw e;
  }

  try {
    const r = await fetch(`data/market.json?t=${ts}`, { cache: "no-store", signal });
    const j = await r.json();
    marketItems = normalizeMarketItems(j);
  } catch (e) {
    if (e?.name === "AbortError") throw e;
    marketItems = [];
  }
}

function patchLocalItemStock(itemId, stock) {
  const idx = marketItems.findIndex((i) => String(i.id) === String(itemId));
  if (idx === -1) return;
  marketItems[idx] = { ...marketItems[idx], stock: Math.max(0, Math.floor(Number(stock) || 0)) };
}

const ICONS = {
  coin: `<svg class="h-5 w-5 shrink-0 text-accent" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path stroke-linecap="round" d="M12 7v10M9.5 9.5h5M9.5 14.5h5"/></svg>`,
};

function bindMarketPageHandlers(outlet) {
  outlet.querySelector("#market-open-login")?.addEventListener("click", () => {
    globalThis.__siteOpenLogin?.();
  });

  outlet.querySelectorAll(".market-buy").forEach((btn) => {
    btn.addEventListener("click", async () => {
      if (btn.disabled) return;
      const itemId = btn.getAttribute("data-item-id");
      const price = Number(btn.getAttribute("data-price")) || 0;
      const stock = Number(btn.getAttribute("data-stock")) || 0;
      if (!itemId || price <= 0 || stock <= 0) return;

      const current = await fetchSessionUser();
      if (!current) {
        globalThis.__siteOpenLogin?.();
        return;
      }
      const balance = Number(current.coins) || 0;
      if (balance < price) {
        showToast(t("marketToastInsufficient"), "info");
        return;
      }

      btn.disabled = true;
      const { ok, status, data } = await postMarketPurchase(itemId);
      if (!ok) {
        if (data?.error === "out_of_stock" || status === 409) {
          showToast(t("marketToastOutOfStock"), "info");
          await loadMarketJson();
          marketUser = await fetchSessionUser();
          renderCards(outlet, marketUser);
          return;
        }
        if (data?.error === "funds") {
          showToast(t("marketToastInsufficient"), "info");
          globalThis.__siteRefreshUser?.();
        } else if (data?.error === "auth") {
          showToast(t("marketToastSession"), "info");
        } else {
          showToast(t("marketToastFailed"), "error");
        }
        btn.disabled = stock > 0 && price > 0;
        return;
      }

      if (data?.item?.id != null && data?.item?.stock != null) {
        patchLocalItemStock(data.item.id, data.item.stock);
      }
      showToast(`${t("marketToastPurchasedPrefix")} ${data?.item?.title || itemId}`, "info");
      globalThis.__siteRefreshUser?.();
      await loadMarketJson();
      marketUser = await fetchSessionUser();
      renderCards(outlet, marketUser);
    });
  });
}

function renderCards(outlet, user) {
  marketUser = user;
  const loggedIn = !!user;
  const coins = user?.coins ?? 0;
  const coinsFmt = formatCoinsDisplay(coins);

  const cards = marketItems.length
    ? marketItems
        .map((item) => {
          const id = escapeHtml(String(item.id ?? ""));
          const title = escapeHtml(String(item.title ?? ""));
          const desc = escapeHtml(String(item.description ?? ""));
          const price = Number(item.price) || 0;
          const stock = itemStock(item);
          const priceFmt = formatCoinsDisplay(price);
          const logoRaw = String(item.logo ?? "").trim();
          const initial = escapeHtml((item.title || "?").slice(0, 2).toUpperCase());
          const outOfStock = stock <= 0;
          const imgHead = logoRaw
            ? `<div class="relative aspect-[16/10] w-full overflow-hidden border-b border-white/[0.06] bg-[#0a0f16]">
                <div class="pointer-events-none absolute inset-0 z-[1] bg-gradient-to-t from-[#181f2e]/88 via-transparent to-white/[0.02] opacity-80 transition-opacity duration-300 group-hover:opacity-60"></div>
                <img src="${escapeHtml(logoRaw)}" alt="" class="market-card-img relative z-0 h-full w-full object-contain p-4 transition-transform duration-500 group-hover:scale-[1.03]" loading="lazy" decoding="async" onerror="this.style.display='none';this.nextElementSibling?.classList.remove('hidden');this.nextElementSibling?.classList.add('flex')"/>
                <div class="absolute inset-0 z-0 hidden items-center justify-center bg-[#0a0f16] p-4" aria-hidden="true"><span class="text-3xl font-black text-white/20">${initial}</span></div>
              </div>`
            : `<div class="relative flex aspect-[16/10] w-full items-center justify-center overflow-hidden border-b border-white/[0.06] bg-gradient-to-br from-[#1e2a3d] via-[#141b26] to-[#0a0f16]" aria-hidden="true">
                <div class="pointer-events-none absolute inset-0 bg-[radial-gradient(ellipse_at_30%_20%,rgba(22,119,255,0.12),transparent_55%)]"></div>
                <span class="relative text-3xl font-black tracking-tight text-white/15">${initial}</span>
              </div>`;
          const lowBalance = loggedIn && price > 0 && coins < price;
          const disabled = outOfStock || price <= 0;
          const btnClass = disabled
            ? "k-btn k-btn--secondary btn-site-secondary cursor-not-allowed opacity-70"
            : !loggedIn
              ? "k-btn k-btn--primary btn-site-primary"
              : lowBalance
                ? "k-btn k-btn--secondary btn-site-secondary opacity-75"
                : "k-btn k-btn--primary btn-site-primary";
          const btnLabel = outOfStock ? t("marketBuyDisabled") : t("marketBuy");
          const cardOpacity = outOfStock ? "opacity-90" : "";

          return `
      <article class="group relative flex flex-col overflow-hidden rounded-2xl border border-white/[0.07] bg-[#1e2739] shadow-[0_12px_40px_-16px_rgba(0,0,0,0.55)] ring-1 ring-white/[0.04] transition-all duration-300 hover:-translate-y-1 hover:border-accent/20 hover:shadow-[0_24px_48px_-20px_rgba(22,119,255,0.14)] hover:ring-accent/15 ${cardOpacity}">
        ${imgHead}
        <div class="flex min-h-0 flex-1 flex-col p-5 sm:p-6">
          <h2 class="text-lg font-semibold leading-snug tracking-tight text-white sm:text-[1.05rem]">${title}</h2>
          ${stockBadgeHtml(stock)}
          <div class="mt-3 max-h-[7.5rem] flex-1 overflow-y-auto pr-1 text-sm leading-relaxed text-slate-400 [scrollbar-width:thin] [scrollbar-color:rgba(22,119,255,0.35)_transparent] whitespace-pre-line">${desc}</div>
          <div class="mt-5 flex flex-wrap items-end justify-between gap-3 border-t border-white/[0.06] pt-5">
            <div class="flex min-w-0 flex-col gap-0.5">
              <span class="text-[10px] font-semibold uppercase tracking-wider text-slate-500">${t("marketPrice")}</span>
              <span class="inline-flex items-center gap-2 text-lg font-bold tabular-nums tracking-tight text-accent sm:text-xl">
                ${ICONS.coin.replace("h-5 w-5", "h-4 w-4 sm:h-5 sm:w-5")}
                <span>${priceFmt} <span class="text-sm font-semibold text-slate-400">${t("marketCoinWord")}</span></span>
              </span>
            </div>
            <button type="button" class="k-btn k-btn--primary market-buy shrink-0 ${btnClass} rounded-xl px-5 py-2.5 text-sm font-semibold shadow-lg shadow-black/20" data-item-id="${id}" data-price="${price}" data-stock="${stock}" ${disabled ? "disabled" : ""}>
              ${escapeHtml(btnLabel)}
            </button>
          </div>
        </div>
      </article>`;
        })
        .join("")
    : `<div class="col-span-full flex flex-col items-center justify-center rounded-2xl border border-dashed border-white/10 bg-white/[0.02] px-8 py-16 text-center">
        <div class="mb-4 flex h-14 w-14 items-center justify-center rounded-2xl bg-white/[0.04] ring-1 ring-white/10">
          <svg class="h-7 w-7 text-slate-500" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path stroke-linecap="round" stroke-linejoin="round" d="M20 7l-8-4-8 4m16 0l-8 4m8-4v10l-8 4m0-10L4 7m8 4v10M4 7v10l8 4"/></svg>
        </div>
        <p class="text-base font-medium text-slate-300">${t("marketEmptyTitle")}</p>
        <p class="mt-1 max-w-sm text-sm text-slate-500">${t("marketEmptyHint")}</p>
      </div>`;

  const balanceBlock = loggedIn
    ? `<div class="flex flex-wrap items-stretch gap-4 sm:items-center">
        <div class="flex min-w-[200px] flex-1 items-center gap-4 rounded-2xl border border-accent/25 bg-accent/[0.07] px-5 py-4 shadow-[inset_0_1px_0_rgba(255,255,255,0.06)] backdrop-blur-sm">
          <div class="flex h-12 w-12 shrink-0 items-center justify-center rounded-xl bg-accent/15 ring-1 ring-accent/25">${ICONS.coin.replace("h-5 w-5", "h-6 w-6")}</div>
          <div>
            <p class="text-[11px] font-semibold uppercase tracking-wider text-slate-400">${t("marketBalanceLabel")}</p>
            <p class="mt-0.5 text-2xl font-bold tabular-nums tracking-tight text-white"><span class="market-balance-num">${coinsFmt}</span> <span class="text-base font-semibold text-slate-400">${t("marketCoinWord")}</span></p>
          </div>
        </div>
      </div>`
    : `<div class="flex flex-col gap-3 rounded-2xl border border-white/[0.08] bg-white/[0.03] px-5 py-4 sm:flex-row sm:items-center sm:justify-between">
        <p class="text-sm text-slate-400">${t("marketGuestHint")}</p>
        <button type="button" class="k-btn k-btn--primary btn-site-primary w-full shrink-0 rounded-xl px-5 py-2.5 text-sm font-semibold sm:w-auto" id="market-open-login">${t("marketLoginCta")}</button>
      </div>`;

  outlet.innerHTML = `
    <div class="relative w-full min-w-0 space-y-6 pb-4">
      <div class="pointer-events-none absolute -right-24 -top-24 h-64 w-64 rounded-full bg-accent/10 blur-3xl"></div>
      <div class="pointer-events-none absolute -bottom-16 -left-20 h-56 w-56 rounded-full bg-accent-deep/15 blur-3xl"></div>

      <header class="relative overflow-hidden rounded-3xl border border-white/[0.08] bg-[#1e2739] p-4 shadow-panel ring-1 ring-white/[0.04] sm:p-6">
        <div class="pointer-events-none absolute inset-0 bg-[radial-gradient(ellipse_80%_60%_at_100%_0%,rgba(22,119,255,0.09),transparent)]"></div>
        <div class="relative space-y-3">
          <div>
            <h1 class="text-3xl font-bold tracking-tight text-white sm:text-4xl">${t("marketPageTitle")}</h1>
            <p class="mt-2 max-w-2xl whitespace-pre-line text-[15px] leading-relaxed text-slate-400 sm:text-base">${escapeHtml(t("marketIntro"))}</p>
          </div>
          ${balanceBlock}
        </div>
      </header>

      <section aria-label="${escapeHtml(t("marketSectionAria"))}">
        <h2 class="sr-only">${escapeHtml(t("marketSectionSr"))}</h2>
        <div class="grid gap-6 sm:grid-cols-2 xl:grid-cols-3">${cards}</div>
      </section>
    </div>`;

  bindMarketPageHandlers(outlet);
}

async function refreshMarketStockIfChanged() {
  if (!marketOutlet) return;
  const before = marketStockSignature(marketItems);
  try {
    await loadMarketJson();
  } catch {
    return;
  }
  if (before !== marketStockSignature(marketItems)) {
    const user = marketUser ?? (await fetchSessionUser());
    renderCards(marketOutlet, user);
  }
}

function startMarketPolling(outlet) {
  marketOutlet = outlet;
  marketPollAbort = new AbortController();

  if (marketVisibilityHandler) {
    document.removeEventListener("visibilitychange", marketVisibilityHandler);
  }
  marketVisibilityHandler = () => {
    if (document.visibilityState === "visible") {
      void refreshMarketStockIfChanged();
    }
  };
  document.addEventListener("visibilitychange", marketVisibilityHandler);

  if (marketPollTimer) clearInterval(marketPollTimer);
  marketPollTimer = setInterval(() => {
    void refreshMarketStockIfChanged();
  }, MARKET_POLL_MS);
}

export function destroyMarketPage() {
  if (marketPollTimer) {
    clearInterval(marketPollTimer);
    marketPollTimer = null;
  }
  if (marketPollAbort) {
    marketPollAbort.abort();
    marketPollAbort = null;
  }
  if (marketVisibilityHandler) {
    document.removeEventListener("visibilitychange", marketVisibilityHandler);
    marketVisibilityHandler = null;
  }
  marketOutlet = null;
  marketUser = null;
}

export async function renderMarketPage(outlet) {
  destroyMarketPage();
  await loadMarketJson();
  const user = await fetchSessionUser();
  renderCards(outlet, user);
  startMarketPolling(outlet);
}
