import { api } from "./lib/api.js";
import { getToken, setToken, clearToken, isLoggedIn } from "./lib/auth.js";
import { setStreakBadge } from "./lib/badge.js";
import { enqueue, flushQueue } from "./lib/offlineQueue.js";
import { registerPwa, wirePwaInstall, subscribePush } from "./lib/pwa.js";
import { wireAppUpdates } from "./lib/updates.js";
import { renderSlots, renderHeatmap, updateStats, showToast, showConfetti, showEasterEgg } from "./lib/ui.js";

const STATUS = { upcoming: "Noch nicht", pending: "Jetzt!", overdue: "Überfällig", snoozed: "Snoozed", taken: "Genommen", missed: "Verpasst" };

function showScreen(id) {
  document.querySelectorAll(".screen").forEach((s) => { s.hidden = s.id !== id; });
}

function wirePinForm() {
  const form = document.getElementById("pinForm");
  const input = document.getElementById("pinInput");
  const errEl = document.getElementById("loginError");

  input.addEventListener("input", () => {
    const digits = input.value.replace(/\D/g, "").slice(0, 6);
    if (input.value !== digits) input.value = digits;
    errEl.hidden = true;
  });

  form.addEventListener("submit", async (e) => {
    e.preventDefault();
    const pin = input.value.trim();
    if (pin.length < 4) return;

    errEl.hidden = true;
    try {
      const { token } = await api.login(pin);
      setToken(token);
      input.value = "";
      await initApp();
    } catch {
      errEl.textContent = "Falscher PIN. Dein Gehirn auch.";
      errEl.hidden = false;
      input.value = "";
      input.focus();
    }
  });
}

function wireTabs() {
  document.querySelectorAll(".tab").forEach((tab) => {
    tab.addEventListener("click", () => {
      document.querySelectorAll(".tab").forEach((t) => t.classList.remove("active"));
      document.querySelectorAll(".tabPanel").forEach((p) => p.hidden = true);
      tab.classList.add("active");
      const panel = document.getElementById(`tab-${tab.dataset.tab}`);
      panel.hidden = false;
      if (tab.dataset.tab === "history") loadHistory();
    });
  });
}

async function handleTake(slotId) {
  const card = document.querySelector(`[data-slot="${slotId}"]`);
  try {
    if (!navigator.onLine) {
      await enqueue({ slot_id: slotId, status: "taken" });
      showToast("Offline gespeichert — wird synchronisiert.");
      return;
    }
    const result = await api.log({ slot_id: slotId, status: "taken" });
    card?.classList.add("dopamin");
    showConfetti();
    showToast(result.message);
    if (result.new_milestones?.length) {
      for (const m of result.new_milestones) {
        showEasterEgg(m.title, "Achievement freigeschaltet!");
      }
    }
    await refreshDashboard(result.stats);
  } catch (e) {
    await enqueue({ slot_id: slotId, status: "taken" });
    showToast("Gespeichert — Sync folgt.");
  }
}

async function handleSnooze(slotId, minutes) {
  try {
    const result = await api.snooze(slotId, minutes);
    showToast(result.message || `Snooze +${minutes} Min`);
    await refreshDashboard();
  } catch (e) {
    showToast("Snooze fehlgeschlagen.");
  }
}

const MOTIVATION_CACHE_KEY = "medis-motivation-day";

function showMotivationFromCache(day) {
  const el = document.getElementById("motivationText");
  const cached = JSON.parse(sessionStorage.getItem(MOTIVATION_CACHE_KEY) || "null");
  if (cached?.day === day && cached?.text) {
    el.textContent = cached.text;
    return true;
  }
  return false;
}

async function loadMotivation(day) {
  try {
    const motivation = await api.roast();
    sessionStorage.setItem(MOTIVATION_CACHE_KEY, JSON.stringify({ day: motivation.day, text: motivation.text }));
    document.getElementById("motivationText").textContent = motivation.text;
  } catch {
    document.getElementById("motivationText").textContent = "Dein Gehirn ist nicht kaputt. Es wartet nur auf den richtigen Treiber.";
  }
}

async function refreshDashboard(stats) {
  const today = await api.today();
  renderSlots(today.slots, handleTake, handleSnooze);

  if (!showMotivationFromCache(today.day)) {
    document.getElementById("motivationText").textContent = "…";
    loadMotivation(today.day);
  }

  const s = stats || await api.stats();
  updateStats(s);
  await setStreakBadge(s.streak);
}

async function loadHistory() {
  const data = await api.history(90);
  renderHeatmap(data.days);
  updateStats(data.stats);
}

async function handleDeepLink() {
  const params = new URLSearchParams(location.search);
  const slot = params.get("slot");
  if (params.get("action") === "take" && slot) {
    await handleTake(slot);
    history.replaceState({}, "", "/");
  } else if (params.get("action") === "snooze" && slot) {
    const minutes = parseInt(params.get("minutes") || "15", 10);
    await handleSnooze(slot, minutes);
    history.replaceState({}, "", "/");
  }
}

async function initApp() {
  showScreen("mainScreen");
  wireTabs();
  wirePwaInstall();
  document.getElementById("logoutBtn").addEventListener("click", () => {
    clearToken();
    location.reload();
  });

  document.getElementById("enablePush").addEventListener("click", async () => {
    const statusEl = document.getElementById("pushStatus");
    try {
      const perm = await Notification.requestPermission();
      if (perm !== "granted") { statusEl.textContent = "Permission verweigert."; return; }
      const { key } = await api.vapidKey();
      if (!key) { statusEl.textContent = "VAPID keys nicht konfiguriert."; return; }
      const sub = await subscribePush(key);
      await api.pushSubscribe(sub);
      statusEl.textContent = "Push aktiv! Du wirst dezent erinnert.";
    } catch (e) {
      statusEl.textContent = e.message || "Push-Setup fehlgeschlagen.";
    }
  });

  await flushQueue((data) => api.log(data));
  await refreshDashboard();
  await handleDeepLink();
}

navigator.serviceWorker?.addEventListener("message", (event) => {
  if (event.data?.type === "SYNC_QUEUE") flushQueue((data) => api.log(data));
});

async function boot() {
  registerPwa();
  wireAppUpdates();
  if (isLoggedIn()) {
    try { await initApp(); return; } catch { clearToken(); }
  }
  showScreen("loginScreen");
  wirePinForm();
}

boot();
