const themeButtons = document.querySelectorAll("[data-theme-toggle]");
const themeStorageKey = "pi-web-theme";
const systemPrefersLight = window.matchMedia("(prefers-color-scheme: light)");

function storedThemeMode() {
  const theme = window.localStorage.getItem(themeStorageKey);
  return theme === "light" || theme === "dark" || theme === "auto" ? theme : "auto";
}

function activeTheme() {
  return document.documentElement.dataset.theme === "light" || document.documentElement.dataset.theme === "dark"
    ? document.documentElement.dataset.theme
    : systemPrefersLight.matches
      ? "light"
      : "dark";
}

function applyThemeMode(mode) {
  if (mode === "light" || mode === "dark") {
    document.documentElement.dataset.theme = mode;
  } else {
    delete document.documentElement.dataset.theme;
  }
  window.localStorage.setItem(themeStorageKey, mode);
  updateThemeButtons(mode);
}

function updateThemeButtons(mode = storedThemeMode()) {
  const active = activeTheme();
  for (const button of themeButtons) {
    button.dataset.theme = mode;
    button.dataset.activeTheme = active;
    const icon = button.querySelector("[data-theme-icon]");
    const label = button.querySelector("[data-theme-label]");
    if (mode === "auto") {
      button.setAttribute("aria-label", `Theme: Auto (${active}). Click to use dark theme.`);
      if (icon !== null) icon.textContent = "◐";
      if (label !== null) label.textContent = "Auto";
    } else if (mode === "light") {
      button.setAttribute("aria-label", "Theme: Light. Click to use automatic theme.");
      if (icon !== null) icon.textContent = "☀";
      if (label !== null) label.textContent = "Light";
    } else {
      button.setAttribute("aria-label", "Theme: Dark. Click to use light theme.");
      if (icon !== null) icon.textContent = "☾";
      if (label !== null) label.textContent = "Dark";
    }
  }
}

updateThemeButtons();
systemPrefersLight.addEventListener("change", () => {
  if (storedThemeMode() === "auto") updateThemeButtons("auto");
});

for (const button of themeButtons) {
  button.addEventListener("click", () => {
    const currentMode = storedThemeMode();
    const nextTheme = currentMode === "auto" ? "dark" : currentMode === "dark" ? "light" : "auto";
    applyThemeMode(nextTheme);
  });
}

const screenshotCarousels = document.querySelectorAll("[data-demo-carousel]");
const reducedMotionQuery = window.matchMedia("(prefers-reduced-motion: reduce)");

function setupScreenshotCarousel(carousel) {
  const gallery = carousel.querySelector("[data-demo-gallery]");
  const controls = carousel.querySelector("[data-demo-controls]");
  const previousButton = carousel.querySelector("[data-demo-prev]");
  const nextButton = carousel.querySelector("[data-demo-next]");
  const dots = Array.from(carousel.querySelectorAll("[data-demo-dot]"));
  const slides = Array.from(carousel.querySelectorAll("[data-demo-slide]"));
  const lightbox = carousel.querySelector("[data-demo-lightbox]");
  const lightboxImage = carousel.querySelector("[data-demo-lightbox-image]");
  const lightboxCaption = carousel.querySelector("[data-demo-lightbox-caption]");
  const lightboxCloseButton = carousel.querySelector("[data-demo-lightbox-close]");
  const lightboxTriggers = Array.from(carousel.querySelectorAll("[data-demo-lightbox-trigger]"));

  if (gallery === null || slides.length === 0) return;

  let updateQueued = false;

  function galleryHasOverflow() {
    return gallery.scrollWidth > gallery.clientWidth + 4;
  }

  function closestSlideIndex() {
    const galleryRect = gallery.getBoundingClientRect();
    const galleryCenter = galleryRect.left + galleryRect.width / 2;
    let closestIndex = 0;
    let closestDistance = Number.POSITIVE_INFINITY;

    slides.forEach((slide, index) => {
      const rect = slide.getBoundingClientRect();
      const distance = Math.abs(rect.left + rect.width / 2 - galleryCenter);
      if (distance < closestDistance) {
        closestIndex = index;
        closestDistance = distance;
      }
    });

    return closestIndex;
  }

  function scrollToSlide(index) {
    const slide = slides[index];
    if (slide === undefined) return;

    slide.scrollIntoView({
      behavior: reducedMotionQuery.matches ? "auto" : "smooth",
      block: "nearest",
      inline: "start",
    });
  }

  function closeLightbox() {
    if (lightbox === null) return;

    if (typeof lightbox.close === "function" && lightbox.open) {
      lightbox.close();
    } else {
      lightbox.removeAttribute("open");
    }
  }

  function openLightbox(trigger) {
    const image = trigger.querySelector("img");
    if (image === null || lightbox === null || lightboxImage === null) return;

    const figure = trigger.closest("figure");
    const captionParts = Array.from(figure?.querySelectorAll("figcaption strong, figcaption span") ?? [])
      .map((node) => node.textContent?.trim())
      .filter(Boolean);
    const caption = captionParts.length > 0 ? captionParts.join(" — ") : "PI WEB screenshot";

    lightboxImage.src = image.currentSrc || image.src;
    lightboxImage.alt = image.alt;
    if (lightboxCaption !== null) lightboxCaption.textContent = caption;

    if (typeof lightbox.showModal === "function") {
      lightbox.showModal();
    } else {
      lightbox.setAttribute("open", "");
    }

    lightboxCloseButton?.focus({ preventScroll: true });
  }

  function updateControls() {
    const overflow = galleryHasOverflow();
    const activeIndex = closestSlideIndex();
    const atStart = gallery.scrollLeft <= 2;
    const atEnd = gallery.scrollLeft + gallery.clientWidth >= gallery.scrollWidth - 2;

    carousel.dataset.overflow = overflow ? "true" : "false";
    gallery.tabIndex = overflow ? 0 : -1;
    if (controls !== null) controls.hidden = !overflow;
    if (previousButton !== null) previousButton.disabled = !overflow || atStart;
    if (nextButton !== null) nextButton.disabled = !overflow || atEnd;

    dots.forEach((dot, index) => {
      dot.setAttribute("aria-current", index === activeIndex ? "true" : "false");
    });
  }

  function queueUpdateControls() {
    if (updateQueued) return;
    updateQueued = true;
    window.requestAnimationFrame(() => {
      updateQueued = false;
      updateControls();
    });
  }

  previousButton?.addEventListener("click", () => {
    scrollToSlide(Math.max(closestSlideIndex() - 1, 0));
  });

  nextButton?.addEventListener("click", () => {
    scrollToSlide(Math.min(closestSlideIndex() + 1, slides.length - 1));
  });

  dots.forEach((dot) => {
    const targetIndex = Number.parseInt(dot.getAttribute("data-demo-dot") ?? "", 10);
    if (Number.isNaN(targetIndex)) return;

    dot.addEventListener("click", () => {
      scrollToSlide(targetIndex);
    });
  });

  lightboxTriggers.forEach((trigger) => {
    trigger.addEventListener("click", () => {
      openLightbox(trigger);
    });
  });

  lightboxCloseButton?.addEventListener("click", closeLightbox);

  lightbox?.addEventListener("click", (event) => {
    if (event.target === lightbox) closeLightbox();
  });

  lightbox?.addEventListener("close", () => {
    lightboxImage?.removeAttribute("src");
  });

  gallery.addEventListener("scroll", queueUpdateControls, { passive: true });
  window.addEventListener("resize", queueUpdateControls);

  if ("ResizeObserver" in window) {
    const resizeObserver = new window.ResizeObserver(queueUpdateControls);
    resizeObserver.observe(gallery);
    slides.forEach((slide) => resizeObserver.observe(slide));
  }

  updateControls();
}

for (const carousel of screenshotCarousels) {
  setupScreenshotCarousel(carousel);
}

const copyButtons = document.querySelectorAll("[data-copy]");

for (const button of copyButtons) {
  button.addEventListener("click", async () => {
    const targetSelector = button.getAttribute("data-copy");
    const target = targetSelector === null ? null : document.querySelector(targetSelector);
    const text = target?.textContent?.replace(/^\s*\$ /gm, "").trim();
    if (!text) return;

    try {
      await navigator.clipboard.writeText(text);
      const original = button.textContent;
      button.textContent = "Copied";
      window.setTimeout(() => {
        button.textContent = original;
      }, 1400);
    } catch {
      button.textContent = "Select code";
    }
  });
}
