import { t, getSiteLocale } from "../config/site.js";
import { fetchChatMessages, postChatMessage, fetchSessionUser } from "../auth/session.js";
import { showToast } from "./toast.js";

/** @type {{ labelKey: string, emojis: string[] }[]} */
const CHAT_EMOJI_SECTIONS = [
  {
    labelKey: "chatEmojiCatFaces",
    emojis: ["😀", "😂", "🥰", "😍", "🤣", "😊", "😎", "😅", "🤔", "😇"],
  },
  {
    labelKey: "chatEmojiCatGestures",
    emojis: ["🤝", "👍", "👎", "🙏", "🙌", "🫡", "💪", "👋", "🤙", "✌️"],
  },
  {
    labelKey: "chatEmojiCatHearts",
    emojis: ["❤️", "🤍", "🔥", "✨", "💯", "⭐", "💬", "📌", "✅", "❌"],
  },
  {
    labelKey: "chatEmojiCatActivity",
    emojis: ["🎉", "🎯", "🪙", "⚡", "🎮", "🏆"],
  },
];

function insertAtCursor(ta, text) {
  const start = ta.selectionStart ?? ta.value.length;
  const end = ta.selectionEnd ?? start;
  ta.focus({ preventScroll: true });
  try {
    ta.setSelectionRange(start, end);
  } catch {
  }
  ta.setRangeText(text, start, end, "end");
  ta.dispatchEvent(new Event("input", { bubbles: true }));
  try {
    const pos = ta.selectionStart ?? ta.value.length;
    ta.setSelectionRange(pos, pos);
  } catch {
  }
}

let pollTimer = null;
let maxMessageId = 0;
let myUserId = 0;
let chatLoggedIn = false;
let bound = false;

function formatChatTime(ts) {
  const sec = typeof ts === "number" ? ts : 0;
  const loc = getSiteLocale() === "en" ? "en-GB" : "tr-TR";
  try {
    return new Date(sec * 1000).toLocaleString(loc, {
      day: "numeric",
      month: "short",
      hour: "2-digit",
      minute: "2-digit",
    });
  } catch {
    return "";
  }
}

function appendMessageEl(list, msg, mine) {
  const wrap = document.createElement("div");
  wrap.className = mine
    ? "site-chat-msg site-chat-msg--mine flex flex-col items-end gap-0.5 pl-6"
    : "site-chat-msg site-chat-msg--other flex flex-col items-start gap-0.5 pr-6";
  wrap.dataset.msgId = String(msg.id);

  const meta = document.createElement("div");
  meta.className =
    "site-chat-msg__meta flex items-center gap-2 text-[10px] " + (mine ? "w-full justify-end" : "");
  const who = document.createElement("span");
  who.className =
    "site-chat-msg__who font-semibold " +
    (!mine && msg.fromManagement ? "site-chat-msg__who--mod" : mine ? "site-chat-msg__who--mine" : "");
  const label = msg.displayName || msg.username;
  who.textContent = mine ? t("chatYou") : label;
  const when = document.createElement("span");
  when.className = "site-chat-msg__time tabular-nums";
  when.textContent = formatChatTime(msg.createdAt);
  meta.appendChild(who);
  if (!mine && msg.fromManagement) {
    const modBadge = document.createElement("span");
    modBadge.className = "site-chat-msg__mod-badge";
    modBadge.textContent = t("chatModerator");
    modBadge.setAttribute("title", t("chatModerator"));
    meta.appendChild(modBadge);
  }
  meta.appendChild(when);

  const bubble = document.createElement("div");
  let bubbleKind = "other";
  if (mine) bubbleKind = "mine";
  else if (msg.fromManagement) bubbleKind = "mod";
  bubble.className = `site-chat-bubble site-chat-bubble--${bubbleKind} max-w-[95%] px-3.5 py-2.5 text-sm leading-relaxed`;

  const text = document.createElement("p");
  text.className = "site-chat-bubble__text whitespace-pre-wrap break-words";
  text.textContent = msg.body;

  bubble.appendChild(text);
  wrap.appendChild(meta);
  wrap.appendChild(bubble);
  list.appendChild(wrap);
  list.scrollTop = list.scrollHeight;
}

function clearPoll() {
  if (pollTimer != null) {
    window.clearInterval(pollTimer);
    pollTimer = null;
  }
}

function getShell() {
  return document.getElementById("site-chat-shell");
}

async function pollNew(listEl) {
  const res = await fetchChatMessages(maxMessageId);
  if (!res.ok || !res.data?.messages?.length) return;
  for (const m of res.data.messages) {
    if (listEl.querySelector(`[data-msg-id="${m.id}"]`)) continue;
    appendMessageEl(listEl, m, m.userId === myUserId);
    maxMessageId = Math.max(maxMessageId, m.id);
  }
}

async function loadInitial(listEl, emptyEl) {
  listEl.innerHTML = "";
  emptyEl.classList.add("hidden");
  maxMessageId = 0;
  const res = await fetchChatMessages();
  if (!res.ok) {
    emptyEl.textContent = t("chatError");
    emptyEl.classList.remove("hidden");
    return;
  }
  const messages = res.data?.messages || [];
  if (messages.length === 0) {
    emptyEl.textContent = t("chatEmpty");
    emptyEl.classList.remove("hidden");
    return;
  }
  for (const m of messages) {
    appendMessageEl(listEl, m, m.userId === myUserId);
    maxMessageId = Math.max(maxMessageId, m.id);
  }
}

function setOpen(open) {
  const shell = getShell();
  if (!shell) return;
  const backdrop = shell.querySelector("#site-chat-backdrop");
  const panel = shell.querySelector("#site-chat-panel");
  const pop = shell.querySelector("#site-chat-emoji-pop");
  const toggle = shell.querySelector("#site-chat-emoji-toggle");
  if (open) {
    shell.classList.remove("hidden");
    document.body.classList.add("overflow-hidden");
    pop?.classList.add("hidden");
    toggle?.setAttribute("aria-expanded", "false");
    requestAnimationFrame(() => {
      backdrop?.classList.remove("opacity-0");
      backdrop?.classList.add("opacity-100");
      panel?.classList.remove("translate-x-full");
    });
  } else {
    backdrop?.classList.add("opacity-0");
    backdrop?.classList.remove("opacity-100");
    panel?.classList.add("translate-x-full");
    pop?.classList.add("hidden");
    toggle?.setAttribute("aria-expanded", "false");
    clearPoll();
    window.setTimeout(() => {
      shell.classList.add("hidden");
      document.body.classList.remove("overflow-hidden");
    }, 280);
  }
}

function setComposerAuthState(loggedIn) {
  chatLoggedIn = loggedIn;
  const shell = getShell();
  if (!shell) return;
  const guestBar = shell.querySelector("#site-chat-guest-bar");
  const composer = shell.querySelector("#site-chat-composer");
  const input = shell.querySelector("#site-chat-input");
  const sendBtn = shell.querySelector("#site-chat-send");
  const emojiToggle = shell.querySelector("#site-chat-emoji-toggle");

  guestBar?.classList.toggle("hidden", loggedIn);
  composer?.classList.toggle("hidden", !loggedIn);
  if (input instanceof HTMLTextAreaElement) {
    input.disabled = !loggedIn;
    input.placeholder = loggedIn ? t("chatPlaceholder") : t("chatLoginToSend");
  }
  if (sendBtn instanceof HTMLButtonElement) sendBtn.disabled = !loggedIn;
  if (emojiToggle instanceof HTMLButtonElement) emojiToggle.disabled = !loggedIn;
}

async function refreshChatAuthState() {
  const shell = getShell();
  if (!shell || shell.classList.contains("hidden")) return;
  const u = await fetchSessionUser();
  myUserId = u?.id ?? 0;
  setComposerAuthState(Boolean(u));
  if (u) {
    const inputEl = shell.querySelector("#site-chat-input");
    inputEl?.focus();
  }
}

async function openPanel() {
  const u = await fetchSessionUser();
  myUserId = u?.id ?? 0;
  const shell = getShell();
  const listEl = shell?.querySelector("#site-chat-messages");
  const emptyEl = shell?.querySelector("#site-chat-empty");
  const inputEl = shell?.querySelector("#site-chat-input");
  if (!listEl || !emptyEl) return;

  setOpen(true);
  setComposerAuthState(Boolean(u));
  emptyEl.textContent = t("chatLoading");
  emptyEl.classList.remove("hidden");
  listEl.innerHTML = "";
  await loadInitial( (listEl),  (emptyEl));

  clearPoll();
  pollTimer = window.setInterval(() => {
    void pollNew( (listEl));
  }, 4000);

  if (u) inputEl?.focus();
}

function closePanel() {
  setOpen(false);
}

export function initSiteChat() {
  const root = document.getElementById("site-chat-root");
  if (!root) return;

  root.innerHTML = `
    <div id="site-chat-shell" class="fixed inset-0 z-[125] hidden">
      <div
        id="site-chat-backdrop"
        class="site-chat-backdrop absolute inset-0 opacity-0 backdrop-blur-md transition-opacity duration-300"
        aria-hidden="true"
      ></div>
      <aside
        id="site-chat-panel"
        class="site-chat-panel absolute right-0 top-0 flex h-[100dvh] w-full max-w-full translate-x-full flex-col overflow-visible transition-transform duration-300 ease-out sm:max-w-none lg:w-[368px]"
        role="dialog"
        aria-modal="true"
        aria-labelledby="site-chat-title"
      >
        <header class="site-chat-header shrink-0 px-4 pb-4 pt-[max(1rem,env(safe-area-inset-top))]">
          <div class="flex items-start justify-between gap-3">
            <div class="min-w-0 pt-0.5">
              <h2 id="site-chat-title" class="site-chat-title home-section-heading text-lg sm:text-xl">${t("chatTitle")}</h2>
              ${
                t("chatSubtitle").trim()
                  ? `<p class="site-chat-subtitle mt-1 text-xs leading-relaxed">${t("chatSubtitle")}</p>`
                  : ""
              }
            </div>
            <button
              type="button"
              id="site-chat-close"
              class="site-chat-close k-btn k-btn--icon btn-site-icon shrink-0 rounded-xl"
              aria-label="${t("chatClose")}"
            >
              <svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/></svg>
            </button>
          </div>
        </header>
        <div id="site-chat-messages" class="site-chat-messages relative z-0 min-h-0 flex-1 space-y-3 overflow-y-auto overscroll-contain px-4 py-4"></div>
        <p id="site-chat-empty" class="site-chat-empty relative z-0 hidden text-center"></p>
        <footer class="site-chat-footer relative z-20 shrink-0 overflow-visible touch-manipulation">
          <div id="site-chat-guest-bar" class="site-chat-guest-bar hidden space-y-3" role="status">
            <p class="site-chat-guest-bar__text text-center leading-relaxed">${t("chatGuestHint")}</p>
            <div class="grid grid-cols-2 gap-2">
              <button type="button" class="auth-open-login k-btn k-btn--secondary btn-site-secondary header-auth-btn">${t("headerLogin")}</button>
              <button type="button" class="auth-open-register k-btn k-btn--primary btn-site-register header-auth-btn">${t("headerRegister")}</button>
            </div>
          </div>
          <div id="site-chat-composer" class="site-chat-composer">
            <div class="site-chat-composer__bar">
              <button
                type="button"
                id="site-chat-emoji-toggle"
                class="site-chat-composer__emoji site-chat-emoji-toggle"
                aria-label="${t("chatEmojiAria")}"
                aria-expanded="false"
                aria-controls="site-chat-emoji-pop"
              >
                <svg class="h-5 w-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path stroke-linecap="round" d="M8 14s1.2 1.5 4 1.5 4-1.5 4-1.5"/><circle cx="9" cy="10" r="0.85" fill="currentColor" stroke="none"/><circle cx="15" cy="10" r="0.85" fill="currentColor" stroke="none"/></svg>
              </button>
              <div class="site-chat-composer__input-wrap">
                <label class="sr-only" for="site-chat-input">${t("chatPlaceholder")}</label>
                <textarea
                  id="site-chat-input"
                  rows="1"
                  maxlength="2000"
                  class="site-chat-input site-chat-composer__input"
                  placeholder="${t("chatPlaceholder")}"
                  autocomplete="off"
                  spellcheck="true"
                  enterkeyhint="send"
                ></textarea>
              </div>
              <button
                type="button"
                id="site-chat-send"
                class="site-chat-send site-chat-composer__send"
                aria-label="${t("chatSend")}"
                title="${t("chatSend")}"
              >
                <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M3.4 20.6 21 12 3.4 3.4l2.8 7.2L17 12l-10.8 1.4-2.8 7.2z"/></svg>
              </button>
            </div>
          </div>
        </footer>
      </aside>
      <div
        id="site-chat-emoji-pop"
        class="site-chat-emoji-pop pointer-events-auto fixed z-[200] hidden touch-manipulation"
        role="dialog"
        aria-label="${t("chatEmojiAria")}"
        aria-hidden="true"
      >
        <div class="site-chat-emoji-pop__panel">
          <header class="site-chat-emoji-pop__head">
            <span class="site-chat-emoji-pop__title">${t("chatEmojiPickerTitle")}</span>
          </header>
          <div id="site-chat-emoji-grid" class="site-chat-emoji-grid" role="listbox" aria-label="${t("chatEmojiAria")}"></div>
        </div>
      </div>
    </div>
  `;

  const shell = getShell();
  const backdrop = root.querySelector("#site-chat-backdrop");
  const closeBtn = root.querySelector("#site-chat-close");
  const sendBtn = root.querySelector("#site-chat-send");
  const input = root.querySelector("#site-chat-input");
  const listEl = root.querySelector("#site-chat-messages");
  const emptyEl = root.querySelector("#site-chat-empty");
  const emojiPop = root.querySelector("#site-chat-emoji-pop");
  const emojiToggle = root.querySelector("#site-chat-emoji-toggle");
  const emojiGrid = root.querySelector("#site-chat-emoji-grid");

  function getChatInput() {
    const el = document.getElementById("site-chat-input");
    return el instanceof HTMLTextAreaElement ? el : null;
  }

  function mountEmojiPicker(grid) {
    if (!grid) return;
    grid.innerHTML = "";
    for (const section of CHAT_EMOJI_SECTIONS) {
      const block = document.createElement("section");
      block.className = "site-chat-emoji-section";
      const label = document.createElement("h3");
      label.className = "site-chat-emoji-section__label";
      label.textContent = t(section.labelKey);
      const cells = document.createElement("div");
      cells.className = "site-chat-emoji-section__grid";
      for (const em of section.emojis) {
        const b = document.createElement("button");
        b.type = "button";
        b.setAttribute("role", "option");
        b.className = "site-chat-emoji-btn";
        b.setAttribute("aria-label", em);
        b.dataset.emoji = em;
        b.textContent = em;
        b.addEventListener("click", (e) => {
          e.preventDefault();
          e.stopPropagation();
          const ta = getChatInput();
          if (ta) insertAtCursor(ta, em);
          setEmojiOpen(false);
        });
        cells.appendChild(b);
      }
      block.appendChild(label);
      block.appendChild(cells);
      grid.appendChild(block);
    }
  }

  mountEmojiPicker(emojiGrid);

  function positionEmojiPop() {
    const sh = getShell();
    if (!sh) return;
    const footer = sh.querySelector("#site-chat-panel footer");
    const pop = sh.querySelector("#site-chat-emoji-pop");
    if (!footer || !pop || pop.classList.contains("hidden")) return;
    const r = footer.getBoundingClientRect();
    const gap = 8;
    pop.style.left = `${r.left}px`;
    pop.style.width = `${Math.max(0, r.width)}px`;
    pop.style.bottom = `${window.innerHeight - r.top + gap}px`;
  }

  let suppressEmojiOutsideClose = false;

  function setEmojiOpen(on) {
    emojiPop?.classList.toggle("hidden", !on);
    emojiPop?.setAttribute("aria-hidden", on ? "false" : "true");
    emojiToggle?.setAttribute("aria-expanded", on ? "true" : "false");
    if (on) {
      requestAnimationFrame(() => {
        positionEmojiPop();
        requestAnimationFrame(positionEmojiPop);
      });
    } else if (emojiPop) {
      emojiPop.style.left = "";
      emojiPop.style.width = "";
      emojiPop.style.bottom = "";
    }
  }

  emojiPop?.addEventListener("click", (e) => {
    e.stopPropagation();
  });

  emojiToggle?.addEventListener("click", (e) => {
    e.stopPropagation();
    if (!chatLoggedIn) {
      globalThis.__siteOpenLogin?.();
      return;
    }
    const willOpen = emojiPop?.classList.contains("hidden") ?? true;
    if (!willOpen) {
      setEmojiOpen(false);
      return;
    }
    suppressEmojiOutsideClose = true;
    setEmojiOpen(true);
    window.setTimeout(() => {
      suppressEmojiOutsideClose = false;
    }, 0);
  });

  const onEmojiViewportChange = () => positionEmojiPop();
  window.addEventListener("resize", onEmojiViewportChange);
  window.visualViewport?.addEventListener("resize", onEmojiViewportChange);
  window.visualViewport?.addEventListener("scroll", onEmojiViewportChange);

  document.addEventListener("click", (e) => {
    if (suppressEmojiOutsideClose) return;
    const t = e.target;
    if (!(t instanceof Node)) return;
    if (emojiPop?.classList.contains("hidden")) return;
    if (emojiPop?.contains(t) || emojiToggle?.contains(t)) return;
    setEmojiOpen(false);
  });

  globalThis.__siteOpenChat = openPanel;
  globalThis.__siteCloseChat = closePanel;
  globalThis.__siteChatRefreshAuth = refreshChatAuthState;

  backdrop?.addEventListener("click", closePanel);
  closeBtn?.addEventListener("click", closePanel);

  async function send() {
    if (!(input instanceof HTMLTextAreaElement) || !listEl || !emptyEl) return;
    if (!chatLoggedIn) {
      globalThis.__siteOpenLogin?.();
      return;
    }
    const text = input.value.trim();
    if (!text) return;
    input.disabled = true;
    if (sendBtn instanceof HTMLButtonElement) sendBtn.disabled = true;
    const res = await postChatMessage(text);
    input.disabled = !chatLoggedIn;
    if (sendBtn instanceof HTMLButtonElement) sendBtn.disabled = !chatLoggedIn;
    if (res.ok && res.data?.message) {
      emptyEl.classList.add("hidden");
      const m = res.data.message;
      if (m.id > maxMessageId) {
        appendMessageEl(listEl, m, true);
        maxMessageId = m.id;
      }
      input.value = "";
      setEmojiOpen(false);
      input.focus();
      return;
    }
    if (res.status === 429) {
      showToast(t("chatRateLimit"), "info");
      return;
    }
    if (res.status === 403 && res.data?.error === "muted") {
      showToast(t("chatMuted"), "error");
      return;
    }
    if (res.status === 401) {
      setComposerAuthState(false);
      globalThis.__siteOpenLogin?.();
      return;
    }
    showToast(t("chatError"), "error");
  }

  sendBtn?.addEventListener("click", () => void send());
  input?.addEventListener("keydown", (e) => {
    if (e.key === "Enter" && !e.shiftKey) {
      e.preventDefault();
      void send();
    }
  });

  if (!bound) {
    bound = true;
    document.body.addEventListener("click", (e) => {
      const t = e.target;
      if (t instanceof Element && t.closest(".site-chat-toggle")) {
        e.preventDefault();
        void openPanel();
      }
    });
    document.addEventListener("keydown", (e) => {
      if (e.key === "Escape" && getShell() && !getShell()?.classList.contains("hidden")) {
        closePanel();
      }
    });
  }
}
