import { api, adminApi } from "./js/api.js";
import { t, setLanguage, getLanguage, initI18n, onLanguageChange, faqMarkdown } from "./js/i18n.js";
import { state, clearUserState, getSavedUsername, setSavedUsername } from "./js/state.js";
import { $, toast } from "./js/dom.js";
import {
  setAuthUI,
  setAuthMode,
  handleAuthError,
  renderWelcome,
  renderPhasePill,
  renderCounts,
  renderMySuggestions,
  renderAllSuggestions,
  renderVotes,
  syncVoteScores,
  renderResults,
  renderPhaseTitles,
  openNewSuggestionModal,
  updatePhaseNav,
  openConfirmModal,
  openResultsRelockModal,
} from "./js/ui.js";
import {
  loadState,
  loadSuggestData,
  loadRevealData,
  loadVoteData,
  loadResults,
  refreshPhaseData,
} from "./js/data.js";
initI18n();

function setupHandlers() {
  const toggleAuth = $("auth-toggle");
  if (toggleAuth) {
    toggleAuth.addEventListener("click", (e) => {
      e.preventDefault();
      setAuthMode(state.authMode === "login" ? "register" : "login");
    });
  }
  setAuthMode(state.authMode);

  const hasConsent = () => document.cookie.split(";").some((c) => c.trim().startsWith("cookie_consent=1"));
  const setConsent = () => { document.cookie = "cookie_consent=1; path=/; max-age=31536000; SameSite=Lax"; };
  const consentRows = document.querySelectorAll(".consent-row");
  const toggleConsentRows = () => {
    const hide = hasConsent();
    consentRows.forEach((row) => row.classList.toggle("hidden", hide));
  };
  toggleConsentRows();
  ["login-consent", "register-consent"].forEach((id) => {
    const box = $(id);
    if (box) {
      box.checked = hasConsent();
      box.addEventListener("change", () => {
        if (box.checked) setConsent();
        toggleConsentRows();
      });
    }
  });

  const loginUser = $("login-username");
  if (loginUser) {
    const markEditing = () => { loginUser.dataset.userEditing = "1"; };
    ["focus", "input", "keydown"].forEach((evt) => loginUser.addEventListener(evt, markEditing));
    loginUser.addEventListener("blur", () => { delete loginUser.dataset.userEditing; });
  }

  setupLanguageSwitchers();

  onLanguageChange(() => {
    updateLanguageButtons();
    renderWelcome();
    renderPhasePill();
    renderCounts();
    renderPhaseTitles();
    renderMySuggestions();
    renderAllSuggestions();
    if (state.phase === "Vote") {
      renderVotes();
      state.votesRendered = true;
      syncVoteScores();
    }
    if (state.phase === "Results") {
      renderResults();
    }
    updatePhaseNav();
  });

  const loginForm = $("login-form");
  if (loginForm) {
    loginForm.addEventListener("submit", async (e) => {
      e.preventDefault();
      const username = $("login-username").value.trim();
      const password = $("login-password").value;
      if (username.length > 24) return toast("Username must be 24 characters or fewer.", true);
      if (!username || !password) return toast(t("auth.needCredentials"), true);
      if (!hasConsent() && !$("login-consent")?.checked) return toast(t("auth.cookieRequired"), true);
      try {
        await api.login({ username, password });
        setConsent();
        setSavedUsername(username);
        state.isAuthenticated = true;
        setAuthUI(true);
        await refreshPhaseData();
        toast(t("toast.loggedIn"));
      } catch (err) {
        if (err?.status === 401) return toast(t("auth.invalidCredentials"), true);
        if (handleAuthError(err, clearUserState)) return;
      }
    });
  }

  const registerForm = $("register-form");
  if (registerForm) {
    registerForm.addEventListener("submit", async (e) => {
      e.preventDefault();
      const username = $("register-username").value.trim();
      const password = $("register-password").value;
      const displayName = $("register-displayName").value.trim();
      const adminKey = $("register-adminkey").value.trim();
      if (!displayName) return toast(t("toast.displayNameRequired") || "Display name is required.", true);
      if (username.length > 24) return toast("Username must be 24 characters or fewer.", true);
      if (displayName.length > 16) return toast("Display name must be 16 characters or fewer.", true);
      if (!username || !password) return toast(t("auth.needCredentials"), true);
      if (!hasConsent() && !$("register-consent")?.checked) return toast(t("auth.cookieRequired"), true);
      try {
        await api.register({ username, password, displayName, adminKey });
        setConsent();
        setSavedUsername(username);
        state.isAuthenticated = true;
        setAuthUI(true);
        await refreshPhaseData();
        toast(t("toast.registered"));
      } catch (err) {
        if (handleAuthError(err, clearUserState)) return;
        toast(err.message, true);
      }
    });
  }

  const openSuggestBtn = $("open-suggest-modal");
  if (openSuggestBtn) {
    openSuggestBtn.addEventListener("click", (e) => {
      e.preventDefault();
      if (openSuggestBtn.disabled) return;
      if (state.phase !== "Suggest") return;
      openNewSuggestionModal();
    });
  }
  const openJokerBtn = $("open-joker-modal");
  if (openJokerBtn) {
    openJokerBtn.addEventListener("click", (e) => {
      e.preventDefault();
      if (state.phase !== "Vote" || !state.hasJoker) return;
      openNewSuggestionModal();
    });
  }

  bindNavButtons();

  $("reset").addEventListener("click", () => adminAction(adminApi.reset, t("admin.resetDone")));
  $("factory-reset").addEventListener("click", () => adminAction(adminApi.factoryReset, t("admin.factoryResetDone")));

  const logoutBtn = $("logout");
  if (logoutBtn) {
    logoutBtn.addEventListener("click", async (e) => {
      e.preventDefault();
      const lastUser = state.me?.username;
      try {
        await api.logout();
      } catch (err) {
        toast(err.message, true);
      }
      clearUserState();
      state.isAuthenticated = false;
      setAuthUI(false);
      if (lastUser) {
        setSavedUsername(lastUser);
        const loginUser = $("login-username");
        if (loginUser) loginUser.value = lastUser;
        const loginPass = $("login-password");
        if (loginPass) loginPass.value = "";
      }
    });
  }

  const adminToggle = $("admin-toggle");
  const adminCard = $("admin-card");
  const adminClose = $("admin-close");
  if (adminToggle && adminCard && adminClose) {
    const togglePanel = (show) => adminCard.classList.toggle("hidden", !show);
    adminToggle.addEventListener("click", () => togglePanel(adminCard.classList.contains("hidden")));
    adminClose.addEventListener("click", () => togglePanel(false));
  }

  document.querySelectorAll(".help-chip").forEach((chip) => {
    chip.addEventListener("click", () => openFaqModal());
  });

  const resultsToggle = $("results-open");
  if (resultsToggle) {
    resultsToggle.addEventListener("change", async (e) => {
      const desired = !!e.target.checked;
      try {
        const resp = await adminApi.setResultsOpen(desired);
        const wasResultsOpen = state.resultsOpen;
        const wasPhase = state.phase;
        state.resultsOpen = resp.resultsOpen;
        if (wasResultsOpen && !resp.resultsOpen && wasPhase === "Results") {
          openResultsRelockModal();
        }
        renderPhasePill();
        toast(t("admin.resultsUpdated"));
        await refreshPhaseData();
      } catch (err) {
        e.target.checked = !desired;
        toast(err.message, true);
      }
    });
  }

  const linkApply = $("link-apply");
  if (linkApply) {
    linkApply.addEventListener("click", async () => {
      const source = Number($("link-source")?.value);
      const target = Number($("link-target")?.value);
      if (!source || !target || source === target) {
        return toast(t("admin.linkValidation"), true);
      }
      try {
        await adminApi.linkSuggestions(source, target);
        toast(t("admin.linkDone"));
        await refreshPhaseData();
      } catch (err) {
        toast(err.message, true);
      }
    });
  }

  const playerTable = $("admin-player-table");
  if (playerTable) {
    playerTable.addEventListener("click", async (e) => {
      const grantBtn = e.target.closest("[data-grant-joker]");
      const deleteBtn = e.target.closest("[data-delete-player]");
      if (grantBtn) {
        const playerId = grantBtn.dataset.grantJoker;
        try {
          await adminApi.grantJoker(playerId);
          toast(t("admin.jokerGranted"));
          await refreshPhaseData();
        } catch (err) {
          toast(err.message, true);
        }
      } else if (deleteBtn) {
        const playerId = deleteBtn.dataset.deletePlayer;
        const name = deleteBtn.dataset.name || "";
        openConfirmModal({
          title: t("admin.deleteTitle"),
          body: t("admin.deleteBody", { name }),
          confirmLabel: t("admin.deleteConfirm"),
          onConfirm: async (close) => {
            try {
              await adminApi.deletePlayer(playerId);
              toast(t("admin.deleteDone"));
              close();
              await refreshPhaseData();
            } catch (err) {
              toast(err.message, true);
            }
          },
        });
      }
    });
  }
}

async function adminAction(fn, successMessage) {
  try {
    await fn();
    toast(successMessage);
    await refreshPhaseData();
  } catch (err) {
    toast(err.message, true);
  }
}

async function main() {
  setupHandlers();
  try {
    await refreshPhaseData();
  } catch (err) {
    toast(err.message, true);
  }
  setInterval(() => {
    refreshPhaseData().catch((err) => {
      if (!handleAuthError(err, clearUserState)) toast(err.message, true);
    });
  }, 4000);
}

main();

function updateLanguageButtons() {
  document.querySelectorAll(".lang-button").forEach((btn) => {
    btn.textContent = "🌐";
    btn.title = t("lang.label");
    btn.setAttribute("aria-label", t("lang.label"));
  });
}

function setupLanguageSwitchers() {
  const switches = document.querySelectorAll(".lang-switch");
  const closeAll = () =>
    switches.forEach((wrap) => wrap.querySelector(".lang-menu")?.classList.add("hidden"));

  switches.forEach((wrap) => {
    const btn = wrap.querySelector(".lang-button");
    const menu = wrap.querySelector(".lang-menu");
    if (!btn || !menu) return;
    btn.addEventListener("click", (e) => {
      e.preventDefault();
      const isHidden = menu.classList.contains("hidden");
      closeAll();
      if (isHidden) menu.classList.remove("hidden");
    });
    menu.querySelectorAll("[data-lang]").forEach((item) =>
      item.addEventListener("click", () => {
        const lang = item.dataset.lang;
        if (lang) setLanguage(lang);
        closeAll();
      }),
    );
  });

  document.addEventListener("click", (e) => {
    if (!e.target.closest(".lang-switch")) closeAll();
  });

  updateLanguageButtons();
}

function bindNavButtons() {
  const makeForward = (id, before) => {
    const btn = $(id);
    if (!btn) return;
    btn.addEventListener("click", async () => {
      try {
        if (before) {
          const proceed = await before();
          if (!proceed) return;
        }
        const resp = await api.nextPhase();
        state.prevPhase = state.phase;
        state.phase = resp.currentPhase;
        state.resultsOpen = resp.resultsOpen ?? state.resultsOpen;
        state.votesRendered = false;
        renderPhasePill();
        await refreshPhaseData();
      } catch (err) {
        toast(err.message, true);
      }
    });
  };

  const makeBack = (id) => {
    const btn = $(id);
    if (!btn) return;
    btn.addEventListener("click", async () => {
      try {
        const resp = await api.prevPhase();
        state.prevPhase = state.phase;
        state.phase = resp.currentPhase;
        state.resultsOpen = resp.resultsOpen ?? state.resultsOpen;
        state.votesRendered = false;
        renderPhasePill();
        await refreshPhaseData();
      } catch (err) {
        toast(err.message, true);
      }
    });
  };

  makeForward("nav-suggest-next", async () => {
    return await new Promise((resolve) => {
      openConfirmModal({
        title: t("nav.freezeModalTitle"),
        body: t("nav.freezeModalBody"),
        confirmLabel: t("nav.next"),
        onConfirm: (close) => {
          close();
          resolve(true);
        },
      });
    });
  });
  makeBack("nav-vote-prev");

  const finalizeBtn = $("finalize-votes");
  if (finalizeBtn) {
    const finalizeVotes = async (desired) => {
      await api.finalizeVotes(desired);
      state.votesFinal = desired;
      renderPhasePill();
      renderVotes();
      toast(desired ? t("vote.finalize") : t("vote.unfinalize"));
    };

    const missingVotes = () => {
      const votedIds = new Set((state.myVotes ?? []).map((v) => v.suggestionId));
      return (state.allSuggestions ?? []).filter((s) => !votedIds.has(s.id));
    };

    finalizeBtn.addEventListener("click", async () => {
      try {
        const desired = !state.votesFinal;
        if (desired) {
          const missing = missingVotes();
          if (missing.length > 0) {
            openConfirmModal({
              title: t("vote.finalizeMissingTitle"),
              body: t("vote.finalizeMissingBody", { count: missing.length }),
              confirmLabel: t("vote.finalizeMissingConfirm"),
              onConfirm: async (close) => {
                await finalizeVotes(desired);
                close();
              },
            });
            return;
          }
        }
        await finalizeVotes(desired);
      } catch (err) {
        toast(err.message, true);
      }
    });
  }
}

function markdownToHtml(md) {
  const lines = md.trim().split(/\r?\n/);
  const html = [];
  let inList = false;
  let inParagraph = false;

  const escapeHtml = (text) =>
    text
      .replace(/&/g, "&amp;")
      .replace(/</g, "&lt;")
      .replace(/>/g, "&gt;");

  const formatInline = (text) =>
    escapeHtml(text)
      .replace(/\*\*(.+?)\*\*/g, "<strong>$1</strong>")
      .replace(/`([^`]+)`/g, "<code>$1</code>");

  const closeParagraph = () => {
    if (inParagraph) {
      html.push("</p>");
      inParagraph = false;
    }
  };

  const closeList = () => {
    if (inList) {
      html.push("</ul>");
      inList = false;
    }
  };

  lines.forEach((rawLine) => {
    const line = rawLine.trimEnd();
    const trimmed = line.trim();
    if (!trimmed) {
      closeParagraph();
      closeList();
      return;
    }

    if (/^-{5,}$/.test(trimmed)) {
      closeParagraph();
      closeList();
      html.push('<hr class="faq-divider" />');
      return;
    }

    const heading = trimmed.match(/^(#{1,3})\s+(.*)$/);
    if (heading) {
      closeParagraph();
      closeList();
      const level = heading[1].length;
      const tag = level === 1 ? "h2" : level === 2 ? "h3" : "h4";
      html.push(`<${tag}>${formatInline(heading[2].trim())}</${tag}>`);
      return;
    }

    if (/^[*-]\s+/.test(trimmed)) {
      closeParagraph();
      if (!inList) {
        html.push("<ul>");
        inList = true;
      }
      const text = trimmed.replace(/^[*-]\s+/, "");
      html.push(`<li>${formatInline(text)}</li>`);
      return;
    }

    if (!inParagraph) {
      html.push("<p>");
      inParagraph = true;
    }
    html.push(formatInline(trimmed));
  });

  closeParagraph();
  closeList();
  return html.join("\n");
}

function openFaqModal() {
  const overlay = document.createElement("div");
  overlay.className = "edit-modal";
  const panel = document.createElement("div");
  panel.className = "edit-panel faq-panel";
  panel.innerHTML = `
    <div class="edit-header">
      <h3>${t("help.title")}</h3>
      <button class="lightbox-close" aria-label="${t("modal.close")}">x</button>
    </div>
    <div class="edit-body">
      <div class="faq-list faq-content"></div>
    </div>
  `;

  const list = panel.querySelector(".faq-list");
  const lang = getLanguage();
  const md = faqMarkdown[lang] ?? faqMarkdown.en;
  list.innerHTML = markdownToHtml(md);

  const close = () => overlay.remove();
  overlay.addEventListener("click", (e) => {
    if (e.target.classList.contains("edit-modal") || e.target.classList.contains("lightbox-close")) close();
  });

  overlay.appendChild(panel);
  document.body.appendChild(overlay);
}
