import { fetchSessionUser, fetchWheelStatus, postWheelSpin } from "../auth/session.js";
import { showToast } from "../components/toast.js";
import { t, getSiteLocale, getSiteLogoUrl } from "../config/site.js";
import { WHEEL_DISC_ROTATION_OFFSET_DEG, WHEEL_SERVER_TO_VISUAL_SLOT } from "../constants/brand.js";

function visualSlotForServerSegment(serverSegment, segmentCount) {
  const n = Math.max(1, Math.min(24, Math.floor(segmentCount)));
  const s = ((serverSegment % n) + n) % n;
  const map = WHEEL_SERVER_TO_VISUAL_SLOT;
  if (Array.isArray(map) && map.length === n && map[s] != null) {
    const v = Math.floor(Number(map[s]));
    if (Number.isFinite(v)) {
      return ((v % n) + n) % n;
    }
  }
  return s;
}

function targetRotationMod(serverSegment, segmentCount) {
  const n = Math.max(1, Math.min(24, Math.floor(segmentCount)));
  const k = visualSlotForServerSegment(serverSegment, n);
  const step = 360 / n;
  const centerDeg = step / 2 + k * step;
  let base = ((-centerDeg) % 360 + 360) % 360;
  const off = Number(WHEEL_DISC_ROTATION_OFFSET_DEG) || 0;
  return ((base + off) % 360 + 360) % 360;
}

const SPIN_MIN_FULL_TURNS = 11;
const SPIN_MAX_FULL_TURNS = 17;

function nextRotationTotal(currentDeg, segment, opts = {}) {
  const segmentCount = opts.segmentCount ?? 6;
  const targetMod = targetRotationMod(segment, segmentCount);
  const cur = ((currentDeg % 360) + 360) % 360;
  let delta = targetMod - cur;
  if (delta < 0) delta += 360;
  const minF = opts.short ? 2 : SPIN_MIN_FULL_TURNS;
  const maxF = opts.short ? 4 : SPIN_MAX_FULL_TURNS;
  const extra = minF + Math.floor(Math.random() * (maxF - minF + 1));
  if (delta === 0) {
    return currentDeg + extra * 360;
  }
  return currentDeg + extra * 360 + delta;
}

const SPIN_DURATION_MS = 6400;
const SPIN_EASING = "cubic-bezier(0.14, 0.82, 0.22, 1)";

function formatCountdown(seconds) {
  const s = Math.max(0, Math.floor(seconds));
  const h = Math.floor(s / 3600);
  const m = Math.floor((s % 3600) / 60);
  const sec = s % 60;
  const en = getSiteLocale() === "en";
  if (h > 0) return en ? `${h}h ${m}m ${sec}s` : `${h} sa ${m} dk ${sec} sn`;
  if (m > 0) return en ? `${m}m ${sec}s` : `${m} dk ${sec} sn`;
  return en ? `${sec}s` : `${sec} sn`;
}

let wheelCountdownTimer = null;

let persistedWheelRotation = 0;

function clearWheelTimer() {
  if (wheelCountdownTimer) {
    clearInterval(wheelCountdownTimer);
    wheelCountdownTimer = null;
  }
}

const WHEEL_DEFAULT_PRIZES = [10, 25, 50, 75, 100, 0];

function formatWheelPrizeSummary(prizes) {
  return prizes.map((n) => (n === 0 ? t("wheelPrizePass") : `${n} ${t("wheelPrizeCoin")}`)).join(", ");
}

function prizesInVisualOrder(prizes) {
  const n = prizes.length;
  const out = new Array(n);
  for (let v = 0; v < n; v++) {
    let prize = prizes[v];
    for (let s = 0; s < n; s++) {
      if (visualSlotForServerSegment(s, n) === v) {
        prize = prizes[s];
        break;
      }
    }
    out[v] = prize;
  }
  return out;
}

const WHEEL_SEGMENT_FILLS = ["#252f44", "#2e3544", "#2c374f", "#2a3a52", "#1e2a3d", "#283a50"];

function polarToXY(cx, cy, r, deg) {
  const rad = ((deg - 90) * Math.PI) / 180;
  return [cx + r * Math.cos(rad), cy + r * Math.sin(rad)];
}

function wheelSlicePath(cx, cy, rOuter, rInner, startDeg, endDeg) {
  const [x0, y0] = polarToXY(cx, cy, rOuter, startDeg);
  const [x1, y1] = polarToXY(cx, cy, rOuter, endDeg);
  const [x2, y2] = polarToXY(cx, cy, rInner, endDeg);
  const [x3, y3] = polarToXY(cx, cy, rInner, startDeg);
  const large = endDeg - startDeg > 180 ? 1 : 0;
  return `M ${x0} ${y0} A ${rOuter} ${rOuter} 0 ${large} 1 ${x1} ${y1} L ${x2} ${y2} A ${rInner} ${rInner} 0 ${large} 0 ${x3} ${y3} Z`;
}

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

function wheelLabelRotation(midDeg) {
  return midDeg >= 90 && midDeg <= 270 ? midDeg + 180 : midDeg;
}

function wheelPrizeSvgLabel(prize, midDeg) {
  const n = Math.floor(Number(prize));
  const pass = !Number.isFinite(n) || n <= 0;
  const [lx, ly] = polarToXY(100, 100, 58, midDeg);
  const rot = wheelLabelRotation(midDeg);
  if (pass) {
    return `<text x="${lx}" y="${ly}" class="wheel-disc__svg-text wheel-disc__svg-text--pass" transform="rotate(${rot} ${lx} ${ly})">${escapeSvgText(t("wheelPrizePass"))}</text>`;
  }
  const unit = escapeSvgText(t("wheelPrizeCoin"));
  return `<text x="${lx}" y="${ly}" class="wheel-disc__svg-text" transform="rotate(${rot} ${lx} ${ly})">
    <tspan class="wheel-disc__svg-amount" x="${lx}" dy="-0.15em">${n}</tspan>
    <tspan class="wheel-disc__svg-unit" x="${lx}" dy="1.05em">${unit}</tspan>
  </text>`;
}

function buildTextWheelDiscHtml(prizes, wheelRotation) {
  const visual = prizesInVisualOrder(prizes);
  const n = visual.length;
  const step = 360 / n;
  const cx = 100;
  const cy = 100;
  const rOuter = 96;
  const rInner = 26;

  const slices = visual
    .map((prize, i) => {
      const start = i * step;
      const end = start + step;
      const mid = start + step / 2;
      const fill = WHEEL_SEGMENT_FILLS[i % WHEEL_SEGMENT_FILLS.length];
      const d = wheelSlicePath(cx, cy, rOuter, rInner, start, end);
      const divider = (() => {
        const [x0, y0] = polarToXY(cx, cy, rInner, start);
        const [x1, y1] = polarToXY(cx, cy, rOuter, start);
        return `<line x1="${x0}" y1="${y0}" x2="${x1}" y2="${y1}" class="wheel-disc__svg-divider"/>`;
      })();
      return `<g class="wheel-disc__svg-seg">
        <path d="${d}" fill="${fill}" class="wheel-disc__svg-slice"/>
        ${divider}
        ${wheelPrizeSvgLabel(prize, mid)}
      </g>`;
    })
    .join("");

  const logoSrc = escapeSvgText(getSiteLogoUrl());
  return `<div
    id="wheel-disc"
    class="wheel-disc wheel-disc--svg relative origin-center rounded-full will-change-transform"
    style="--wheel-segments:${n};transform:rotate(${wheelRotation}deg) translateZ(0);transition:transform 0ms linear;backface-visibility:hidden"
  >
    <svg class="wheel-disc__svg block h-full w-full" viewBox="0 0 200 200" role="img" aria-hidden="true">
      <defs>
        <filter id="wheel-disc-shadow" x="-20%" y="-20%" width="140%" height="140%">
          <feDropShadow dx="0" dy="2" stdDeviation="3" flood-color="#000" flood-opacity="0.45"/>
        </filter>
        <radialGradient id="wheel-disc-vignette" cx="50%" cy="50%" r="50%">
          <stop offset="55%" stop-color="transparent"/>
          <stop offset="100%" stop-color="rgba(0,0,0,0.35)"/>
        </radialGradient>
      </defs>
      <circle cx="${cx}" cy="${cy}" r="${rOuter + 2}" class="wheel-disc__svg-rim-outer"/>
      <g filter="url(#wheel-disc-shadow)">
        ${slices}
        <circle cx="${cx}" cy="${cy}" r="${rOuter}" fill="url(#wheel-disc-vignette)" pointer-events="none"/>
      </g>
      <circle cx="${cx}" cy="${cy}" r="${rOuter}" fill="none" class="wheel-disc__svg-rim"/>
      <circle cx="${cx}" cy="${cy}" r="${rInner}" fill="#1e2739" class="wheel-disc__svg-hub-ring"/>
    </svg>
    <div class="wheel-disc__hub">
      <img src="${logoSrc}" alt="" class="h-[60%] w-[60%] object-contain" width="40" height="40" loading="eager" decoding="async" onerror="this.style.display='none';this.nextElementSibling?.classList.remove('hidden')" />
      <span class="hidden text-[10px] font-bold tracking-tight text-accent-bright">A</span>
    </div>
  </div>`;
}

export async function renderWheelPage(outlet) {
  if (!outlet) return;
  clearWheelTimer();

  const statusRes = await fetchWheelStatus();
  const data = statusRes.data || {};

  if (data.enabled === false) {
    outlet.innerHTML = `
      <section class="relative w-full min-w-0 space-y-8 px-1 pb-4">
        <header class="relative overflow-hidden rounded-3xl border border-white/[0.08] bg-[#1e2739] p-8 shadow-panel ring-1 ring-white/[0.04] sm:p-10">
          <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">
            <span class="inline-flex items-center gap-2 rounded-full border border-accent/25 bg-accent/10 px-3 py-1 text-[11px] font-semibold uppercase tracking-[0.18em] text-accent-bright">${t("wheelEyebrow")}</span>
            <h1 class="text-3xl font-bold tracking-tight text-white sm:text-4xl">${t("wheelTitleDaily")}</h1>
            <p class="max-w-2xl text-sm leading-relaxed text-slate-400 sm:text-base">${t("wheelDisabledMsg")}</p>
          </div>
        </header>
      </section>`;
    return;
  }

  const user = await fetchSessionUser();
  if (!user) {
    persistedWheelRotation = 0;
  }

  if (!user) {
    outlet.innerHTML = `
      <section class="relative w-full min-w-0 space-y-8 px-1 pb-4">
        <header class="relative overflow-hidden rounded-3xl border border-white/[0.08] bg-[#1e2739] p-8 shadow-panel ring-1 ring-white/[0.04] sm:p-10">
          <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">
            <span class="inline-flex items-center gap-2 rounded-full border border-accent/25 bg-accent/10 px-3 py-1 text-[11px] font-semibold uppercase tracking-[0.18em] text-accent-bright">${t("wheelEyebrowDaily")}</span>
            <h1 class="text-3xl font-bold tracking-tight text-white sm:text-4xl">${t("wheelTitleMain")}</h1>
            <p class="max-w-2xl text-sm leading-relaxed text-slate-400 sm:text-base">${t("wheelGuestHint")}</p>
            <button type="button" id="wheel-open-login" class="k-btn k-btn--primary btn-site-primary mt-2 rounded-xl px-5 py-2.5 text-sm font-semibold">${t("marketLoginCta")}</button>
          </div>
        </header>
      </section>`;
    outlet.querySelector("#wheel-open-login")?.addEventListener("click", () => globalThis.__siteOpenLogin?.());
    return;
  }

  const wheelRotation = persistedWheelRotation;
  let spinning = false;
  let canSpin = !!data.can_spin;
  let secondsLeft = Number(data.seconds_left) || 0;
  let coins = Number(data.coins) ?? 0;
  const prizes =
    Array.isArray(data.prizes) && data.prizes.length === 6
      ? data.prizes.map((x) => {
          const n = Math.floor(Number(x));
          return Number.isFinite(n) && n >= 0 ? Math.min(99999999, n) : 0;
        })
      : [...WHEEL_DEFAULT_PRIZES];
  const segmentCount = prizes.length;
  const cooldownH = Number(data.cooldown_hours) > 0 ? Number(data.cooldown_hours) : 24;
  const prizeSummary = formatWheelPrizeSummary(prizes);

  function buildHtml() {
    const disabled = !canSpin || spinning;
    const btnClass = disabled
      ? "k-btn k-btn--secondary btn-site-secondary cursor-not-allowed opacity-60"
      : "k-btn k-btn--primary btn-site-action wheel-spin-btn";
    const coinsLoc = getSiteLocale() === "en" ? "en-US" : "tr-TR";
    const coinsStr = Number(coins).toLocaleString(coinsLoc);

    const cooldownMsg =
      !canSpin && secondsLeft > 0
        ? `<p class="mt-4 rounded-xl border border-white/[0.06] bg-white/[0.03] px-4 py-3 text-center text-sm text-slate-400">${t("wheelNextSpinLabel")} <span class="font-mono tabular-nums font-semibold text-accent" id="wheel-countdown">${formatCountdown(secondsLeft)}</span></p>`
        : "";

    const ruleLine = t("wheelCooldownRule").replace("{hours}", String(cooldownH));
    const spinCreditLine = t("wheelSpinCredit").replace("{hours}", String(cooldownH));

    return `
      <section class="relative w-full min-w-0 space-y-8 px-1 pb-4">
        <header class="relative overflow-hidden rounded-3xl border border-white/[0.08] bg-[#1e2739] p-8 shadow-panel ring-1 ring-white/[0.04] sm:p-10">
          <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">
            <span class="inline-flex items-center gap-2 rounded-full border border-accent/25 bg-accent/10 px-3 py-1 text-[11px] font-semibold uppercase tracking-[0.18em] text-accent-bright">${t("wheelEyebrow")}</span>
            <h1 class="text-3xl font-bold tracking-tight text-white sm:text-4xl">${t("wheelTitleReward")}</h1>
            <p class="max-w-2xl text-sm leading-relaxed text-slate-400 sm:text-base">${ruleLine} <span class="text-slate-300">${prizeSummary}</span>.</p>
          </div>
        </header>
      <div class="relative w-full min-w-0 px-0 pb-10 pt-2 sm:px-1">
        <div class="pointer-events-none absolute -right-24 -top-8 h-56 w-56 rounded-full bg-accent/12 blur-3xl"></div>
        <div class="pointer-events-none absolute -bottom-12 -left-16 h-48 w-48 rounded-full bg-accent-deep/15 blur-3xl"></div>

        <div class="relative overflow-hidden rounded-3xl border border-white/[0.08] bg-[#1e2739] shadow-[0_24px_60px_-20px_rgba(0,0,0,0.55)] ring-1 ring-white/[0.05]">
          <div class="pointer-events-none absolute inset-0 bg-[radial-gradient(ellipse_90%_50%_at_50%_-10%,rgba(22,119,255,0.08),transparent)]"></div>

          <div class="relative flex flex-wrap items-center justify-between gap-3 border-b border-white/[0.06] px-6 py-5">
            <div class="flex items-center gap-3">
              <span class="flex h-10 w-10 shrink-0 items-center justify-center rounded-xl bg-accent/10 ring-1 ring-accent/25" aria-hidden="true">
                <svg class="h-5 w-5 text-accent" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75"><circle cx="12" cy="12" r="9"/><path stroke-linecap="round" d="M12 7v10M9.5 9.5h5M9.5 14.5h5"/></svg>
              </span>
              <div>
                <p class="text-sm font-semibold text-white">${t("wheelCardSubtitle")}</p>
                <p class="text-xs text-slate-500">${spinCreditLine}</p>
              </div>
            </div>
            <div class="rounded-full border border-white/[0.08] bg-white/[0.04] px-3 py-1.5 text-xs text-slate-400">
              ${t("wheelBalancePrefix")} <strong class="tabular-nums text-slate-200">${coinsStr}</strong> ${t("wheelPrizeCoin")}
            </div>
          </div>

          <div class="relative px-6 pb-8 pt-6 sm:px-10">
            <h2 class="text-center text-2xl font-bold tracking-tight text-white sm:text-3xl">${t("wheelSpinHeading")}</h2>
            ${cooldownMsg}

            <div class="wheel-stage">
              <div class="wheel-stage__pointer" aria-hidden="true"></div>
              <div class="wheel-stage__frame-outer">
                <div class="wheel-stage__frame-inner">
                ${buildTextWheelDiscHtml(prizes, wheelRotation)}
                </div>
              </div>
            </div>

            <button
              type="button"
              id="wheel-spin-btn"
              class="k-btn wheel-spin-btn mt-10 w-full rounded-xl py-3.5 text-sm font-semibold tracking-wide transition ${btnClass}"
              ${disabled ? "disabled" : ""}
            >
              ${spinning ? t("wheelBtnSpinning") : !canSpin ? t("wheelBtnWait") : t("wheelBtnSpin")}
            </button>
          </div>
        </div>
      </div>
      </section>`;
  }

  outlet.innerHTML = buildHtml();

  const disc = outlet.querySelector("#wheel-disc");
  const btn = outlet.querySelector("#wheel-spin-btn");
  const countdownEl = outlet.querySelector("#wheel-countdown");

  if (!canSpin && secondsLeft > 0 && countdownEl) {
    wheelCountdownTimer = setInterval(() => {
      secondsLeft -= 1;
      if (secondsLeft <= 0) {
        clearWheelTimer();
        canSpin = true;
        void renderWheelPage(outlet);
        return;
      }
      countdownEl.textContent = formatCountdown(secondsLeft);
    }, 1000);
  }

  btn?.addEventListener("click", async () => {
    if (spinning || !canSpin) return;
    spinning = true;
    btn.disabled = true;
    btn.textContent = t("wheelBtnSpinning");
    btn.className =
      "mt-10 w-full rounded-xl py-3.5 text-sm font-semibold tracking-wide transition cursor-not-allowed k-btn k-btn--secondary btn-site-secondary opacity-60";

    const res = await postWheelSpin();
    if (!res.ok || !res.data) {
      spinning = false;
      if (res.data?.error === "disabled") {
        showToast(t("wheelToastDisabled"), "info");
        void renderWheelPage(outlet);
        return;
      }
      if (res.data?.error === "cooldown") {
        showToast(t("wheelToastCooldown"), "info");
        secondsLeft = Number(res.data.seconds_left) || 0;
        canSpin = false;
        globalThis.__siteRefreshUser?.();
        void renderWheelPage(outlet);
        return;
      }
      if (res.status === 401) {
        showToast(t("wheelToastAuth"), "info");
        globalThis.__siteOpenLogin?.();
      } else {
        showToast(t("wheelToastUnavailable"), "error");
      }
      btn.disabled = false;
      btn.textContent = t("wheelBtnSpin");
      return;
    }

    const segment = Number(res.data.segment);
    const amount = Number(res.data.amount);
    const newCoins = Number(res.data.coins);
    const nextAt = Number(res.data.next_spin_at);
    const fromDeg = persistedWheelRotation;
    const reducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
    const target = nextRotationTotal(fromDeg, segment, { short: reducedMotion, segmentCount });

    if (!disc) {
      persistedWheelRotation = target;
      coins = newCoins;
      canSpin = false;
      secondsLeft = Math.max(0, nextAt - Math.floor(Date.now() / 1000));
      showToast(
        amount <= 0 ? t("wheelToastPass") : t("wheelToastWin").replace("{amount}", String(amount)),
        "info"
      );
      globalThis.__siteRefreshUser?.();
      void renderWheelPage(outlet);
      return;
    }

    disc.style.transition = "none";
    disc.style.transform = `rotate(${fromDeg}deg) translateZ(0)`;
    void disc.offsetWidth;

    const spinMs = reducedMotion ? 450 : SPIN_DURATION_MS;
    const spinEase = reducedMotion ? "ease-out" : SPIN_EASING;

    requestAnimationFrame(() => {
      requestAnimationFrame(() => {
        if (!disc.isConnected) return;
        disc.style.transition = `transform ${spinMs}ms ${spinEase}`;
        disc.style.transform = `rotate(${target}deg) translateZ(0)`;
      });
    });

    let finished = false;
    const done = () => {
      if (finished) return;
      finished = true;
      persistedWheelRotation = target;
      spinning = false;
      coins = newCoins;
      canSpin = false;
      secondsLeft = Math.max(0, nextAt - Math.floor(Date.now() / 1000));
      showToast(
        amount <= 0 ? t("wheelToastPass") : t("wheelToastWin").replace("{amount}", String(amount)),
        "info"
      );
      globalThis.__siteRefreshUser?.();
      void renderWheelPage(outlet);
    };

    let fallbackTimer = 0;
    const onEnd = (ev) => {
      if (ev.propertyName !== "transform") return;
      disc.removeEventListener("transitionend", onEnd);
      clearTimeout(fallbackTimer);
      done();
    };
    disc.addEventListener("transitionend", onEnd);
    fallbackTimer = setTimeout(() => {
      disc.removeEventListener("transitionend", onEnd);
      done();
    }, spinMs + 400);
  });
}
