/*
  ui.js — Save Pet
  ---------------------------------------------------------------
  All DOM/screen logic lives here. game.js knows nothing about the
  DOM — it calls the small set of SP.UI.on*()/update*() hooks below
  and this file decides how to present that on screen. Keeping the
  split this way means the canvas engine can be unit-tested headless
  (see /tools in the dev notes) while all the "app shell" chrome
  stays ordinary, easy-to-restyle HTML/CSS.
*/
window.SP = window.SP || {};

SP.UI = (function () {
  "use strict";
  const U = SP.Utils, CFG = SP.Config;
  let lastResultExtra = {};

  /* ---------------- screen management ---------------- */
  function showScreen(name) {
    U.$all(".screen").forEach(function (s) { s.classList.add("hidden"); });
    const target = document.getElementById("screen-" + name);
    if (target) target.classList.remove("hidden");
    if (name === "game" && SP.Game && SP.Game.onResize) {
      SP.Game.onResize(); // canvas was display:none until this line; measure it now
    }
    if (name === "menu") {
      SP.Audio.playMusic("menu");
      updateCoins(SP.Storage.data.coins);
      checkDailyBonusAvailable();
    }
    if (name === "level-select") renderLevelGrid();
    if (name === "achievements") renderAchievements();
    if (name === "settings") renderSettings();
  }

  function wireBackButtons() {
    U.$all("[data-back]").forEach(function (btn) {
      U.on(btn, "click", function () { showScreen(btn.getAttribute("data-back")); });
    });
  }

  /* ---------------- shared coin display ---------------- */
  function updateCoins(coins) {
    U.$all(".coin-value").forEach(function (el) { el.textContent = coins; });
  }

  /* ---------------- level select ---------------- */
  function starIcons(n) {
    let s = "";
    for (let i = 0; i < 3; i++) s += (i < n ? "\u2605" : "\u2606");
    return s;
  }

  function renderWorldTabs() {
    const tabs = U.$("#world-tabs");
    if (!tabs) return;
    tabs.innerHTML = "";
    SP.Levels.WORLDS.forEach(function (w) {
      const b = U.ce("button", "world-tab", w.name);
      U.on(b, "click", function () {
        const el = document.getElementById("world-section-" + w.id);
        if (el) el.scrollIntoView({ behavior: "smooth", block: "start" });
      });
      tabs.appendChild(b);
    });
  }

  function renderLevelGrid() {
    const grid = U.$("#level-grid");
    if (!grid) return;
    grid.innerHTML = "";
    const data = SP.Storage.data;
    for (let w = 1; w <= CFG.TOTAL_WORLDS; w++) {
      const meta = SP.Levels.worldMeta(w);
      const section = U.ce("div", "world-section");
      section.id = "world-section-" + w;
      section.appendChild(U.ce("div", "world-heading", meta.name));
      const rowGrid = U.ce("div", "world-grid");
      for (let li = 1; li <= CFG.LEVELS_PER_WORLD; li++) {
        const id = (w - 1) * CFG.LEVELS_PER_WORLD + li;
        const rec = data.levels[String(id)];
        const unlocked = id <= data.unlockedLevel;
        const btn = U.ce("button", "level-btn" + (unlocked ? "" : " locked") + (rec && rec.completed ? " completed" : ""));
        btn.setAttribute("data-level-id", id);
        if (!unlocked) {
          btn.innerHTML = '<span class="lock-icon">\uD83D\uDD12</span>';
          btn.disabled = true;
        } else {
          const stars = rec ? rec.stars : 0;
          btn.innerHTML = '<span class="level-num">' + id + '</span><span class="level-stars">' + starIcons(stars) + "</span>";
          U.on(btn, "click", function () { startLevelFlow(id); });
        }
        rowGrid.appendChild(btn);
      }
      section.appendChild(rowGrid);
      grid.appendChild(section);
    }
  }

  function startLevelFlow(id) {
    const lv = SP.Levels.getLevel(id);
    showScreen("game");
    SP.Game.startLevel(lv, "level");
  }

  /* ---------------- daily login bonus ---------------- */
  function checkDailyBonusAvailable() {
    const btn = U.$("#btn-daily-bonus");
    if (!btn) return;
    const today = U.todayKey();
    if (SP.Storage.data.daily.lastLoginBonusDate !== today) btn.classList.remove("hidden");
    else btn.classList.add("hidden");
  }

  function claimDailyBonus() {
    const data = SP.Storage.data;
    const today = U.todayKey();
    if (data.daily.lastLoginBonusDate === today) return;
    const yesterday = U.todayKey(new Date(Date.now() - 86400000));
    data.daily.loginStreak = data.daily.lastLoginBonusDate === yesterday ? data.daily.loginStreak + 1 : 1;
    data.daily.lastLoginBonusDate = today;
    const bonus = 20 + Math.min(50, (data.daily.loginStreak - 1) * 5);
    data.coins += bonus;
    data.stats.totalCoinsEarnedLifetime += bonus;
    SP.Storage.save();
    updateCoins(data.coins);
    showToast("+" + bonus + " coins! Day " + data.daily.loginStreak + " streak");
    SP.Audio.play("coin");
    U.$("#btn-daily-bonus").classList.add("hidden");
    SP.Achievements.check();
  }

  /* ---------------- game HUD ---------------- */
  function updateInk(current, max) {
    const fill = U.$("#ink-fill");
    if (!fill) return;
    const pct = max > 0 ? U.clamp(current / max, 0, 1) * 100 : 0;
    fill.style.width = pct + "%";
    fill.classList.toggle("ink-low", pct < 15);
  }

  function updateHearts(health) {
    const el = U.$("#hud-hearts");
    if (!el) return;
    let s = "";
    for (let i = 0; i < CFG.PET_MAX_HEALTH; i++) s += (i < health ? "\u2764\uFE0F" : "\uD83E\uDD0D");
    el.textContent = s;
  }

  function updateTimerDisplay(seconds, isEndless) {
    const el = U.$("#hud-timer");
    if (!el) return;
    el.textContent = isEndless ? U.formatTime(seconds) + " \u2B06" : U.formatTime(Math.max(0, seconds));
  }

  function onLevelStart(levelConfig, mode) {
    const label = U.$("#hud-level-label");
    if (label) {
      label.textContent = mode === "level" ? ("World " + levelConfig.world + " \u00B7 Level " + levelConfig.id) :
        mode === "daily" ? "Daily Challenge" : mode === "endless" ? "Endless Mode" : "Random Challenge";
    }
    updateCoins(SP.Storage.data.coins);
    updateHearts(CFG.PET_MAX_HEALTH);
    updateInk(levelConfig.inkBudgetRef, levelConfig.inkBudgetRef);
    updateTimerDisplay(mode === "endless" ? 0 : (levelConfig.surviveTime || 0), mode === "endless");
  }

  function onTick(state) {
    updateTimerDisplay(state.mode === "endless" ? state.elapsed : state.timeRemaining, state.mode === "endless");
    updateInk(state.ink, state.inkBudget);
  }

  function onHit(health) {
    updateHearts(health);
    const el = U.$("#screen-game");
    if (el) {
      el.classList.add("flash-hit");
      setTimeout(function () { el.classList.remove("flash-hit"); }, 200);
    }
  }

  /* ---------------- pause + quick settings ---------------- */
  function syncQuickSettings() {
    const s = SP.Storage.data.settings;
    const m = U.$("#chk-music"); if (m) m.checked = s.musicOn;
    const sfx = U.$("#chk-sfx"); if (sfx) sfx.checked = s.sfxOn;
  }

  function wireGameControls() {
    U.on(U.$("#btn-pause"), "click", function () {
      SP.Game.pause();
      syncQuickSettings();
      U.$("#modal-pause").classList.remove("hidden");
    });
    U.on(U.$("#btn-resume"), "click", function () { U.$("#modal-pause").classList.add("hidden"); SP.Game.resume(); });
    U.on(U.$("#btn-restart-pause"), "click", function () { U.$("#modal-pause").classList.add("hidden"); SP.Game.restart(); });
    U.on(U.$("#btn-quit-pause"), "click", function () {
      U.$("#modal-pause").classList.add("hidden");
      SP.Game.quitToMenu();
      showScreen("menu");
    });
    U.on(U.$("#btn-undo"), "click", function () { SP.Game.undoLastLine(); });
    U.on(U.$("#btn-hint"), "click", function () { SP.Game.useHint(); });
    U.on(U.$("#chk-music"), "change", function (e) {
      SP.Storage.data.settings.musicOn = e.target.checked; SP.Storage.save(); SP.Audio.setMusicEnabled(e.target.checked);
    });
    U.on(U.$("#chk-sfx"), "change", function (e) { SP.Storage.data.settings.sfxOn = e.target.checked; SP.Storage.save(); });
  }

  /* ---------------- result modal (win / lose / endless / random) ---------------- */
  function setLastResult(extra) { lastResultExtra = extra || {}; }

  function renderAndShowResultModal(result) {
    const content = U.$("#modal-result-content");
    if (!content) return;
    const won = result.won;
    let html = "";
    if (result.mode === "level" || result.mode === "daily") {
      const stars = result.stars || 0;
      html += '<div class="result-icon">' + (won ? "\uD83C\uDF89" : "\uD83D\uDE3F") + "</div>";
      html += "<h2>" + (won ? "Level Complete!" : "Not Quite!") + "</h2>";
      if (won) {
        html += '<div class="result-stars">' + [0, 1, 2].map(function (i) {
          return '<span class="star' + (i < stars ? " filled" : "") + '">\u2605</span>';
        }).join("") + "</div>";
        html += '<p class="result-sub">+' + (lastResultExtra.coinsEarned || 0) + " coins earned</p>";
        if (lastResultExtra.firstClear) html += '<p class="result-badge">First Clear Bonus +' + CFG.FIRST_CLEAR_BONUS + "</p>";
        if (result.mode === "daily") html += '<p class="result-badge">\uD83D\uDD25 ' + (lastResultExtra.dailyStreak || 1) + " day streak</p>";
      } else {
        html += '<p class="result-sub">The bees got through. Try a different wall!</p>';
      }
    } else {
      html += '<div class="result-icon">' + (result.mode === "endless" ? "\u267E\uFE0F" : "\uD83C\uDFB2") + "</div>";
      html += "<h2>Run Complete</h2>";
      html += '<p class="result-sub">Survived ' + U.formatTime(result.elapsed) + " \u00B7 " + result.beesPopped + " bees popped</p>";
      html += '<p class="result-sub">+' + (lastResultExtra.coinsEarned || 0) + " coins" + (lastResultExtra.improved ? " \u00B7 New Best!" : "") + "</p>";
    }
    content.innerHTML = html;

    const btnRow = U.ce("div", "result-buttons");
    if (result.mode === "level") {
      if (won && result.level.id < CFG.TOTAL_LEVELS) {
        const nextBtn = U.ce("button", "btn btn-primary", "Next Level \u25B6");
        U.on(nextBtn, "click", function () { closeResultModal(); startLevelFlow(result.level.id + 1); });
        btnRow.appendChild(nextBtn);
      }
      const retryBtn = U.ce("button", "btn " + (won ? "btn-secondary" : "btn-primary"), won ? "Replay" : "Retry");
      U.on(retryBtn, "click", function () { closeResultModal(); showScreen("game"); SP.Game.restart(); });
      btnRow.appendChild(retryBtn);
      if (!won) {
        const skipBtn = U.ce("button", "btn btn-ghost", "Skip (watch ad) \u25B6");
        U.on(skipBtn, "click", function () {
          closeResultModal();
          SP.Ads.showRewarded(function () { SP.Game.skipCurrentLevel(); }, function () {});
        });
        btnRow.appendChild(skipBtn);
      }
    } else {
      const retryBtn = U.ce("button", "btn btn-primary", "Play Again");
      U.on(retryBtn, "click", function () {
        closeResultModal();
        showScreen("game");
        if (result.mode === "endless") SP.Game.startLevel(SP.Levels.getEndlessConfig(), "endless");
        else SP.Game.startLevel(SP.Levels.getRandomLevel(), "random");
      });
      btnRow.appendChild(retryBtn);
    }
    const menuBtn = U.ce("button", "btn btn-ghost", "Main Menu");
    U.on(menuBtn, "click", function () { closeResultModal(); SP.Game.quitToMenu(); showScreen("menu"); });
    btnRow.appendChild(menuBtn);
    content.appendChild(btnRow);

    U.$("#modal-result").classList.remove("hidden");
  }

  function closeResultModal() { U.$("#modal-result").classList.add("hidden"); }

  function onRunEnd(result) {
    if (result.mode === "level" && result.won && result.level.id % CFG.INTERSTITIAL_EVERY_N_LEVELS === 0) {
      SP.Ads.showInterstitial(function () { renderAndShowResultModal(result); });
    } else {
      renderAndShowResultModal(result);
    }
  }

  function onLevelSkipped(id) {
    showToast("Level " + id + " skipped!");
    showScreen("level-select");
  }

  /* ---------------- rewarded / interstitial placeholders ---------------- */
  function showRewardedPlaceholder(onReward, onClose) {
    const modal = U.$("#modal-rewarded"), body = U.$("#modal-rewarded-body");
    if (!modal || !body) { onReward(); onClose(); return; }
    let seconds = CFG.REWARDED_AD_SECONDS;
    body.textContent = "Ad playing\u2026 " + seconds + "s";
    modal.classList.remove("hidden");
    const timer = setInterval(function () {
      seconds--;
      if (seconds <= 0) {
        clearInterval(timer);
        body.textContent = "Reward granted!";
        setTimeout(function () { modal.classList.add("hidden"); onReward(); onClose(); }, 500);
      } else {
        body.textContent = "Ad playing\u2026 " + seconds + "s";
      }
    }, 1000);
  }

  function showInterstitialPlaceholder(onClose) {
    const modal = U.$("#modal-interstitial");
    if (!modal) { onClose(); return; }
    modal.classList.remove("hidden");
    setTimeout(function () { modal.classList.add("hidden"); onClose(); }, 1600);
  }

  /* ---------------- settings screen ---------------- */
  function renderSettings() {
    const s = SP.Storage.data.settings;
    const set = function (sel, prop, val) { const el = U.$(sel); if (el) el[prop] = val; };
    set("#set-music", "checked", s.musicOn);
    set("#set-sfx", "checked", s.sfxOn);
    set("#set-haptics", "checked", s.hapticsOn);
    set("#set-reduce", "checked", s.reduceEffects);
    set("#set-music-vol", "value", s.musicVolume);
    set("#set-sfx-vol", "value", s.sfxVolume);
  }

  function toggleFullscreen() {
    try {
      if (!document.fullscreenElement) {
        const el = document.documentElement;
        const req = el.requestFullscreen || el.webkitRequestFullscreen || el.msRequestFullscreen;
        if (req) req.call(el);
      } else {
        const exit = document.exitFullscreen || document.webkitExitFullscreen || document.msExitFullscreen;
        if (exit) exit.call(document);
      }
    } catch (e) { /* fullscreen not supported — ignore */ }
  }

  function wireSettings() {
    U.on(U.$("#set-music"), "change", function (e) { SP.Storage.data.settings.musicOn = e.target.checked; SP.Storage.save(); SP.Audio.setMusicEnabled(e.target.checked); });
    U.on(U.$("#set-sfx"), "change", function (e) { SP.Storage.data.settings.sfxOn = e.target.checked; SP.Storage.save(); });
    U.on(U.$("#set-haptics"), "change", function (e) { SP.Storage.data.settings.hapticsOn = e.target.checked; SP.Storage.save(); });
    U.on(U.$("#set-reduce"), "change", function (e) { SP.Storage.data.settings.reduceEffects = e.target.checked; SP.Storage.save(); });
    U.on(U.$("#set-music-vol"), "input", function (e) { SP.Storage.data.settings.musicVolume = parseFloat(e.target.value); SP.Storage.save(); SP.Audio.refreshVolumes(); });
    U.on(U.$("#set-sfx-vol"), "input", function (e) { SP.Storage.data.settings.sfxVolume = parseFloat(e.target.value); SP.Storage.save(); });
    U.on(U.$("#btn-fullscreen"), "click", toggleFullscreen);
    U.on(U.$("#btn-reset-progress"), "click", function () {
      if (window.confirm("Reset ALL progress, coins, and achievements? This cannot be undone.")) {
        SP.Storage.reset();
        updateCoins(SP.Storage.data.coins);
        showToast("Progress reset");
        showScreen("menu");
      }
    });
  }

  /* ---------------- achievements screen ---------------- */
  function renderAchievements() {
    const list = U.$("#achievements-list");
    if (!list) return;
    list.innerHTML = "";
    SP.Achievements.getAll().forEach(function (a) {
      const item = U.ce("div", "achievement-item" + (a.unlocked ? " unlocked" : ""));
      item.innerHTML = '<span class="ach-icon">' + a.icon + '</span><div class="ach-text"><div class="ach-name">' + a.name +
        '</div><div class="ach-desc">' + a.desc + "</div></div>" + (a.unlocked ? '<span class="ach-check">\u2713</span>' : "");
      list.appendChild(item);
    });
  }

  /* ---------------- toasts ---------------- */
  function showToast(msg) {
    const container = U.$("#toast-container");
    if (!container) return;
    const el = U.ce("div", "toast", msg);
    container.appendChild(el);
    requestAnimationFrame(function () { el.classList.add("show"); });
    setTimeout(function () { el.classList.remove("show"); setTimeout(function () { el.remove(); }, 300); }, 2200);
  }

  function showAchievementToast(def) {
    const container = U.$("#toast-container");
    if (!container) return;
    const el = U.ce("div", "toast toast--achievement",
      '<span class="toast-icon">' + def.icon + '</span><div><div class="toast-title">Achievement Unlocked!</div><div class="toast-sub">' + def.name + "</div></div>");
    container.appendChild(el);
    requestAnimationFrame(function () { el.classList.add("show"); });
    SP.Audio.play("achievement");
    U.vibrate([0, 30, 40, 30]);
    setTimeout(function () { el.classList.remove("show"); setTimeout(function () { el.remove(); }, 300); }, 3200);
  }

  /* ---------------- install / update banners (driven by pwa.js) ---------------- */
  function showInstallBanner() { const b = U.$("#install-banner"); if (b) b.classList.remove("hidden"); }
  function hideInstallBanner() { const b = U.$("#install-banner"); if (b) b.classList.add("hidden"); }
  function showUpdateBanner() { const b = U.$("#update-banner"); if (b) b.classList.remove("hidden"); }

  function wireInstallAndUpdate() {
    U.on(U.$("#btn-install"), "click", function () { if (SP.PWA) SP.PWA.promptInstall(); });
    U.on(U.$("#btn-install-dismiss"), "click", hideInstallBanner);
    U.on(U.$("#btn-update-reload"), "click", function () { if (SP.PWA) SP.PWA.applyUpdate(); });
  }

  /* ---------------- menu wiring ---------------- */
  function wireMenu() {
    U.on(U.$("#btn-play"), "click", function () { showScreen("level-select"); });
    U.on(U.$("#btn-daily"), "click", function () { showScreen("game"); SP.Game.startLevel(SP.Levels.getDailyLevel(), "daily"); });
    U.on(U.$("#btn-endless"), "click", function () { showScreen("game"); SP.Game.startLevel(SP.Levels.getEndlessConfig(), "endless"); });
    U.on(U.$("#btn-random"), "click", function () { showScreen("game"); SP.Game.startLevel(SP.Levels.getRandomLevel(), "random"); });
    U.on(U.$("#btn-achievements"), "click", function () { showScreen("achievements"); });
    U.on(U.$("#btn-howto"), "click", function () { showScreen("howto"); });
    U.on(U.$("#btn-settings"), "click", function () { showScreen("settings"); });
    U.on(U.$("#btn-daily-bonus"), "click", claimDailyBonus);
  }

  function init() {
    const hintCostEl = U.$("#hint-cost");
    if (hintCostEl) hintCostEl.textContent = CFG.HINT_COST;
    wireMenu();
    wireGameControls();
    wireSettings();
    wireBackButtons();
    wireInstallAndUpdate();
    renderWorldTabs();
    renderLevelGrid();
    updateCoins(SP.Storage.data.coins);
    checkDailyBonusAvailable();
    showScreen("menu");
  }

  return {
    init: init, showScreen: showScreen,
    updateInk: updateInk, updateCoins: updateCoins,
    onLevelStart: onLevelStart, onTick: onTick, onHit: onHit, onRunEnd: onRunEnd,
    setLastResult: setLastResult, onLevelSkipped: onLevelSkipped,
    showToast: showToast, showAchievementToast: showAchievementToast,
    showRewardedPlaceholder: showRewardedPlaceholder, showInterstitialPlaceholder: showInterstitialPlaceholder,
    renderLevelGrid: renderLevelGrid, renderAchievements: renderAchievements,
    showInstallBanner: showInstallBanner, hideInstallBanner: hideInstallBanner, showUpdateBanner: showUpdateBanner
  };
})();
