import {
  GAME_CONFIG,
  seedStr,
  updateResetCountdown,
  fetchConfig,
  fetchGridForSeed,
  fetchAndApplyActivePlayers,
  updateEconomyDisplay,
  loadEconScores,
  loadVictoryPoints,
  loadDbInfo,
  loadElementBonus,
  loadMilitaryDeductions,
  applyRealtimeSnapshot,
  applyCellUpdate,
  applyTeamQuotaUpdate,
  applyMilitaryDeductionsUpdate,
  refreshFromServer,
  refreshGridDisplay,
  loadPlayfieldMask,
  draw,
} from "./game.js";

import {
  tryRestoreSession,
  showAuthOverlay,
  hideAuthOverlay,
} from "./auth.js";

import {
  startRealtime,
  restartRealtime,
} from "./realtime.js";

// ── DOM refs ──────────────────────────────────────────────────────────────────

const hint            = document.getElementById("hint");
const cooldownEl      = document.getElementById("cooldownConfig");
const burgerBtn       = document.getElementById("burgerBtn");
const closeMenuBtn    = document.getElementById("closeMenuBtn");
const infoColumn      = document.getElementById("infoColumn");

// ── Polling ───────────────────────────────────────────────────────────────────

let configPollTimer = 0;
let scorePollTimer  = 0;
let resetTimer      = null;
let victoryPollTimer = 0;
let gridPollTimer = 0;
let fallbackPollingEnabled = false;
let syncInFlight = false;

function clearFallbackTimers() {
  clearTimeout(configPollTimer);
  clearTimeout(scorePollTimer);
  if (victoryPollTimer) {
    clearInterval(victoryPollTimer);
    victoryPollTimer = 0;
  }
  if (gridPollTimer) {
    clearInterval(gridPollTimer);
    gridPollTimer = 0;
  }
}

function scheduleConfigPoll() {
  if (!fallbackPollingEnabled) return;
  clearTimeout(configPollTimer);
  const ms = Math.max(5_000, GAME_CONFIG.configReloadIntervalSeconds * 1_000);
  configPollTimer = window.setTimeout(async () => {
    try {
      const changed = await fetchConfig();
      if (changed) await refreshFromServer();
    } catch { /* ignore */ }
    scheduleConfigPoll();
  }, ms);
}

const ECON_TICK_SECONDS = 5;

function scheduleScorePoll() {
  if (!fallbackPollingEnabled) return;
  clearTimeout(scorePollTimer);
  scorePollTimer = window.setTimeout(async () => {
    await fetchAndApplyActivePlayers();
    await loadEconScores();
    await loadElementBonus();
    await loadMilitaryDeductions();
    scheduleScorePoll();
  }, ECON_TICK_SECONDS * 1_000);
}

function startFallbackPolling() {
  if (fallbackPollingEnabled) return;
  fallbackPollingEnabled = true;
  scheduleConfigPoll();
  scheduleScorePoll();
  victoryPollTimer = setInterval(loadVictoryPoints, 30_000);
  gridPollTimer = setInterval(refreshGridDisplay, 1_000);
}

function stopFallbackPolling() {
  fallbackPollingEnabled = false;
  clearFallbackTimers();
}

async function syncFromServer() {
  if (syncInFlight) return;
  syncInFlight = true;
  try {
    await refreshFromServer();
    await loadVictoryPoints();
  } finally {
    syncInFlight = false;
  }
}

function handleRealtimeMessage(message) {
  if (!message || typeof message !== "object") return;
  const worldSeed = typeof message.worldSeed === "string" ? message.worldSeed : null;

  if (worldSeed && seedStr && worldSeed !== seedStr) {
    syncFromServer();
    return;
  }

  switch (message.type) {
    case "snapshot":
      applyRealtimeSnapshot(message);
      break;
    case "cell-updated":
      if (message.cell) applyCellUpdate(message.cell);
      break;
    case "team-quota-updated":
      applyTeamQuotaUpdate(message.team, message.actionsRemaining);
      break;
    case "military-deductions-updated":
      applyMilitaryDeductionsUpdate(message.deductions);
      break;
    case "config-updated":
    case "seed-changed":
      syncFromServer();
      break;
    default:
      break;
  }
}

function startRealtimeFlow() {
  startRealtime({
    onOpen: () => {
      stopFallbackPolling();
    },
    onClose: () => {
      startFallbackPolling();
    },
    onMessage: handleRealtimeMessage,
  });
}

// ── Burger / mobile menu ──────────────────────────────────────────────────────

function openMenu() {
  infoColumn.classList.add("infoColumn--open");
}

function closeMenu() {
  infoColumn.classList.remove("infoColumn--open");
}

burgerBtn.addEventListener("click", openMenu);
closeMenuBtn.addEventListener("click", closeMenu);

// Close when clicking outside the panel (on the galaxy overlay)
document.addEventListener("click", (ev) => {
  if (
    infoColumn.classList.contains("infoColumn--open") &&
    !infoColumn.contains(ev.target) &&
    ev.target !== burgerBtn
  ) {
    closeMenu();
  }
});

// ── Boot ──────────────────────────────────────────────────────────────────────

async function boot() {
  // Load the SVG playfield mask before any drawing or data fetch
  await loadPlayfieldMask();

  const restored = await tryRestoreSession();
  if (!restored) {
    showAuthOverlay();
  } else {
    hideAuthOverlay();
  }

  try {
    await fetchConfig();
    try {
      await fetchGridForSeed(seedStr);
    } catch (e) {
      if (e?.message !== "grid_stale") throw e;
      await fetchConfig();
      await fetchGridForSeed(seedStr);
    }
    await fetchAndApplyActivePlayers();
    await loadEconScores();
    await loadVictoryPoints();
    await loadDbInfo();
    await loadElementBonus();
    await loadMilitaryDeductions();
    updateEconomyDisplay();
  } catch {
    hint.textContent = "API unavailable — start the Node server (docker-compose up --build).";
    cooldownEl.textContent = "?";
  }

  draw();

  if (resetTimer) clearInterval(resetTimer);
  resetTimer = setInterval(updateResetCountdown, 1_000);
  updateResetCountdown();

  startRealtimeFlow();

  window.addEventListener("auth:changed", () => {
    restartRealtime();
  });
}

// ── Start ─────────────────────────────────────────────────────────────────────

boot();