import { refreshOffers, getSkillLevel } from "./conveyor.js";
import { getPlotUpgradeCost, getTruckUpgradeCost, getWorldMapUpgradeResearchCost } from "./economy.js";
import { getVisitorCount } from "./income.js";
import { getTimePhase } from "./time-weather.js";
import { canPrestige, doPrestige } from "./prestige.js";
import { playSound, isMusicEnabled } from "./audio.js";
import { questDescription, timePhaseLabel, weatherLabel, prestigeHint } from "./texts-fr.js";
import { GameConfig } from "./config.js";
import { renderWorldMap } from "./ui-world-map.js";
import { renderGrid } from "./ui-grid.js";
import { buildGameBar } from "./ui-render-gamebar.js";
import { buildWorldMapSection, buildGridSection } from "./ui-render-dom-panels.js";

/**
 * @param {{ errEl: HTMLElement }} _setup
 * @returns {{ tabsWrap: HTMLElement, tabContent: HTMLElement, panelZoo: HTMLElement, panelWorld: HTMLElement }}
 */
function createTabsStructure(_setup) {
  const tabsWrap = document.createElement("div");
  tabsWrap.className = "tabs-wrap";
  tabsWrap.setAttribute("aria-label", "Carte du zoo et carte du monde");
  const tabContent = document.createElement("div");
  tabContent.className = "tabs-content";
  const panelZoo = document.createElement("div");
  panelZoo.className = "tab-panel active";
  panelZoo.id = "tab-panel-zoo";
  panelZoo.setAttribute("role", "tabpanel");
  panelZoo.setAttribute("aria-labelledby", "view-toggle");
  const panelWorld = document.createElement("div");
  panelWorld.className = "tab-panel";
  panelWorld.id = "tab-panel-world";
  panelWorld.setAttribute("role", "tabpanel");
  panelWorld.setAttribute("aria-labelledby", "view-toggle");
  return { tabsWrap, tabContent, panelZoo, panelWorld };
}

/**
 * @param {Array<{ descriptionKey: string, target: number, current: number, done: boolean }>} quests
 * @returns {string}
 */
function formatQuestListHtml(quests) {
  return (quests ?? []).map((q) => {
    const desc = questDescription[q.descriptionKey];
    const text = desc ? String(desc).replace("%d", String(q.target)) : q.descriptionKey;
    const done = q.done ? " ✓" : "";
    return `<div class="quest-item ${q.done ? "done" : ""}">${text} : ${q.current}/${q.target}${done}</div>`;
  }).join("");
}

/**
 * @param {object} gameBarResult
 * @param {object} setup
 * @returns {void}
 */
function updateStatusBody(gameBarResult, setup) {
  const { state } = setup;
  const { selected } = setup;
  const {
    statusBarCoins,
    statusBarPlot,
    statusBarCell,
    statusBarSkill,
    statusBarVisitors,
    statusBarOffers,
    statusBarTimeWeather,
    musicBtn,
    autoModeBtn,
    prestigeBtn,
    questListEl,
  } = gameBarResult;
  statusBarCoins.valueEl.textContent = String(Math.floor(state.coins));
  statusBarPlot.valueEl.textContent = String(Math.floor(state.plotLevel));
  statusBarCell.valueEl.textContent = `${Math.floor(selected.x)} ${Math.floor(selected.y)}`;
  statusBarSkill.valueEl.textContent = String(Math.floor(getSkillLevel(state)));
  const visitors = getVisitorCount(state);
  statusBarVisitors.valueEl.textContent = String(Math.floor(visitors));
  const offersCount = (state.conveyorOffers ?? []).length;
  statusBarOffers.valueEl.textContent = String(Math.floor(offersCount));
  const timePhase = getTimePhase(state.timeOfDay ?? 6);
  const weatherVal = weatherLabel[state.weather] ?? state.weather;
  statusBarTimeWeather.valueEl.textContent = `${timePhaseLabel[timePhase.phase]} · ${weatherVal}`;
  statusBarTimeWeather.item.className = "status-bar-item status-bar-time-weather weather-" + (state.weather ?? "sun");
  musicBtn.classList.toggle("muted", !isMusicEnabled());
  autoModeBtn.setAttribute("aria-pressed", state.autoMode ? "true" : "false");
  autoModeBtn.title = state.autoMode ? "Mode automatique (désactiver)" : "Mode automatique (activer)";
  autoModeBtn.setAttribute("aria-label", state.autoMode ? "Mode automatique actif" : "Activer le mode automatique");
  autoModeBtn.textContent = state.autoMode ? "🤖" : "✋";
  prestigeBtn.title = String(prestigeHint).replace("%d", String(GameConfig.Prestige.MinCoinsToReset));
  prestigeBtn.disabled = !canPrestige(state);
  questListEl.innerHTML = formatQuestListHtml(state.quests);
}

/**
 * @param {object} gameBarResult
 * @param {object} setup
 * @returns {() => void}
 */
function createUpdateStatus(gameBarResult, setup) {
  return function updateStatus() {
    updateStatusBody(gameBarResult, setup);
  };
}

/**
 * @param {object} opts
 * @returns {() => void}
 */
function createFullRender(opts) {
  const {
    setup,
    sellZone,
    plotUpgradeZone,
    worldMapUpgradeZone,
    worldMapCounters,
    worldMapCtx,
    gridCtx,
    updateStatus,
  } = opts;
  const { state } = setup;
  return function fullRender() {
    setup.clampSelection();
    updateStatus();
    const canUpTruck = (state.truckLevel ?? 1) < ((GameConfig.Truck && GameConfig.Truck.MaxLevel) || 5)
      && state.coins >= getTruckUpgradeCost(state.truckLevel ?? 1);
    sellZone.classList.toggle("can-upgrade", canUpTruck);
    const truckArrow = sellZone.querySelector(".sell-zone-upgrade-arrow");
    if (truckArrow) truckArrow.style.display = canUpTruck ? "" : "none";
    const plotMaxLevel = GameConfig.Plot.MaxLevel || 8;
    const canUpgradePlot = (state.plotLevel ?? 1) < plotMaxLevel && state.coins >= getPlotUpgradeCost(state.plotLevel ?? 1);
    plotUpgradeZone.classList.toggle("can-upgrade", canUpgradePlot);
    const plotArrow = plotUpgradeZone.querySelector(".plot-upgrade-zone-arrow");
    if (plotArrow) plotArrow.style.display = canUpgradePlot ? "" : "none";
    updateWorldMapUpgradeAndCounters(worldMapUpgradeZone, worldMapCounters, state);
    const eggPurchase = state.eggPurchaseTruck;
    if (eggPurchase && eggPurchase.startAt) {
      const truckLevel = state.truckLevel ?? 1;
      const baseMs = (GameConfig.WorldMap && GameConfig.WorldMap.TruckAnimationMs) || 2500;
      const durationMs = Math.max(1000, (baseMs * 2) / truckLevel);
      if (Date.now() - eggPurchase.startAt >= durationMs) delete state.eggPurchaseTruck;
    }
    renderWorldMap(worldMapCtx);
    renderGrid(gridCtx);
  };
}

/**
 * @param {HTMLElement} worldMapUpgradeZone
 * @param {HTMLElement} worldMapCounters
 * @param {import("./types.js").GameState} state
 * @returns {void}
 */
function updateWorldMapUpgradeAndCounters(worldMapUpgradeZone, worldMapCounters, state) {
  const mapCfg = GameConfig.WorldMap && GameConfig.WorldMap.MapUpgrade;
  const mapMaxLevel = mapCfg ? mapCfg.MaxLevel : 5;
  const currentMapLevel = state.worldMapLevel ?? 1;
  const mapResearchCost = getWorldMapUpgradeResearchCost(currentMapLevel);
  const canUpgradeMap = currentMapLevel < mapMaxLevel && (state.researchPoints ?? 0) >= mapResearchCost;
  worldMapUpgradeZone.classList.toggle("can-upgrade", canUpgradeMap);
  worldMapUpgradeZone.title = currentMapLevel < mapMaxLevel
    ? `Agrandir la carte (${mapResearchCost} unités de recherche)`
    : "Agrandir la carte";
  const mapCostEl = worldMapUpgradeZone.querySelector(".world-map-upgrade-zone-cost");
  if (mapCostEl) mapCostEl.textContent = currentMapLevel < mapMaxLevel ? ` ${mapResearchCost} 🔬` : "";
  const mapArrow = worldMapUpgradeZone.querySelector(".world-map-upgrade-zone-arrow");
  if (mapArrow) mapArrow.style.display = canUpgradeMap ? "" : "none";
  const babiesForSale = (state.saleListings ?? []).filter((s) => s.isBaby).length;
  const animalsForSale = (state.saleListings ?? []).filter((s) => !s.isBaby).length;
  const labsCount = GameConfig.WorldMap && GameConfig.WorldMap.Laboratory ? 1 : 0;
  const zoosCount = (state.worldZoos ?? []).length;
  const citiesCount = (GameConfig.WorldMap && GameConfig.WorldMap.Cities) ? GameConfig.WorldMap.Cities.length : 0;
  worldMapCounters.textContent = "";
  const counterEntries = [
    ["Bébés à vendre", babiesForSale],
    ["Animaux à vendre", animalsForSale],
    ["Laboratoires", labsCount],
    ["Zoos", zoosCount],
    ["Villes", citiesCount],
  ];
  for (const [label, value] of counterEntries) {
    const span = document.createElement("span");
    span.className = "world-map-counter";
    span.title = label;
    span.setAttribute("aria-label", `${label}: ${value}`);
    span.textContent = `${label}: ${value}`;
    worldMapCounters.appendChild(span);
  }
}

/**
 * @param {{ setup: object, gameBarResult: object, worldMapResult: object, gridResult: object }} opts
 * @returns {{ worldMapCtx: object, gridCtx: object }}
 */
function buildFinishContexts(opts) {
  const { setup, worldMapResult, gridResult } = opts;
  const worldMapCtx = {
    worldMapEl: worldMapResult.worldMapEl,
    worldMapTruckEl: worldMapResult.worldMapTruckEl,
    worldMapNpcTrucksEl: worldMapResult.worldMapNpcTrucksEl,
    state: setup.state,
    setState: setup.setState,
    setError: setup.setError,
    playSound,
    animalEmoji: setup.animalEmoji,
    pendingTokenByEggType: setup.pendingTokenByEggType,
  };
  const gridCtx = {
    state: setup.state,
    setState: setup.setState,
    setError: setup.setError,
    playSound,
    gridEl: gridResult.gridEl,
    getHatched: setup.getHatched,
    selected: setup.selected,
    emptyCellChoice: setup.emptyCellChoiceRef,
    selectedTokenId: setup.selectedTokenIdRef,
    lastActionWasDrop: setup.lastActionWasDropRef,
    clampSelection: setup.clampSelection,
    animalEmoji: setup.animalEmoji,
  };
  return { worldMapCtx, gridCtx };
}

/**
 * @param {{ root: HTMLElement, setup: object, gameBarResult: object, worldMapResult: object, gridResult: object, updateStatus: () => void }} opts
 * @returns {() => void}
 */
function finishBuildUIDOM(opts) {
  const { setup, gameBarResult, worldMapResult, gridResult, updateStatus } = opts;
  const { worldMapCtx, gridCtx } = buildFinishContexts(opts);
  renderWorldMap(worldMapCtx);
  renderGrid(gridCtx);
  gameBarResult.prestigeBtn.addEventListener("click", () => {
    if (!canPrestige(setup.state)) return;
    doPrestige(setup.state);
    refreshOffers(setup.state, Math.floor(Date.now() / 1000));
    setup.setError("");
    playSound("upgrade");
    setup.setState();
  });
  const fullRender = createFullRender({
    setup,
    sellZone: gridResult.sellZone,
    plotUpgradeZone: gridResult.plotUpgradeZone,
    worldMapUpgradeZone: worldMapResult.worldMapUpgradeZone,
    worldMapCounters: worldMapResult.worldMapCounters,
    worldMapCtx,
    gridCtx,
    updateStatus,
  });
  fullRender();
  return fullRender;
}

/**
 * @param {HTMLElement} root
 * @param {object} setup
 * @returns {() => void}
 */
export function buildUIDOM(root, setup) {
  const tabs = createTabsStructure(setup);
  const { panelZoo, panelWorld, tabsWrap, tabContent } = tabs;
  const gameBarResult = buildGameBar(setup, panelZoo, panelWorld);
  const worldMapResult = buildWorldMapSection(panelWorld, setup);
  const gridResult = buildGridSection(panelZoo, setup);
  tabsWrap.appendChild(setup.errEl);
  tabContent.appendChild(panelZoo);
  tabContent.appendChild(panelWorld);
  tabsWrap.appendChild(tabContent);
  gameBarResult.gameBarActions.insertBefore(gameBarResult.viewSwitcherWrap, gameBarResult.gameBarActions.firstChild);
  root.appendChild(gameBarResult.gameBar);
  root.appendChild(tabsWrap);
  const updateStatus = createUpdateStatus(gameBarResult, setup);
  return finishBuildUIDOM({ root, setup, gameBarResult, worldMapResult, gridResult, updateStatus });
}
