import './style.css';

/**
 * Runs a lightweight transform-based carousel for Calio post cards.
 */
const initPostCarousel = (carousel) => {
  const track = carousel.querySelector('.calio-post-carousel-track');
  const viewport = carousel.querySelector('.calio-post-carousel-viewport');
  const slides = Array.from(carousel.querySelectorAll('.calio-post-carousel-card'));
  const prev = carousel.querySelector('.calio-post-carousel-arrow.is-prev');
  const next = carousel.querySelector('.calio-post-carousel-arrow.is-next');
  const dots = carousel.querySelector('.calio-post-carousel-dots');

  if (!track || slides.length === 0) {
    return;
  }

  let currentPage = 0;
  let totalPages = 1;
  let autoplayTimer = null;
  let interactionTimer = null;
  let isPointerDown = false;
  let pointerStartX = 0;
  let pointerDeltaX = 0;
  let lastSlidesToShow = 1;

  const clearAutoplay = () => {
    if (autoplayTimer) {
      window.clearInterval(autoplayTimer);
      autoplayTimer = null;
    }
  };

  const clearInteractionTimer = () => {
    if (interactionTimer) {
      window.clearTimeout(interactionTimer);
      interactionTimer = null;
    }
  };

  const getAutoPlayEnabled = () => (carousel.dataset.autoplay || '') === 'yes';
  const getAutoPlaySpeed = () =>
    Number.parseInt(carousel.dataset.autoplaySpeed || '3500', 10);
  const getCenterMode = () => (carousel.dataset.centerMode || '') === 'yes';
  const getPauseOnInteraction = () =>
    (carousel.dataset.pauseOnInteraction || 'yes') === 'yes';

  const applyActiveSlides = (slidesToShow) => {
    const shouldHighlight = (carousel.dataset.highlightActiveSlide || 'yes') === 'yes';
    slides.forEach((slide) => slide.classList.remove('is-active-slide'));

    if (!shouldHighlight) {
      return;
    }

    const start = getCenterMode() ? currentPage : currentPage * slidesToShow;
    const end = Math.min(start + slidesToShow, slides.length);
    const visibleSlides = slides.slice(start, end);
    const activeIndex = Math.floor((visibleSlides.length - 1) / 2);
    if (visibleSlides[activeIndex]) {
      visibleSlides[activeIndex].classList.add('is-active-slide');
    }
  };

  const getSlidesToShow = () => {
    if (window.matchMedia('(max-width: 767px)').matches) {
      return Number.parseInt(carousel.dataset.slidesMobile || '1', 10);
    }

    if (window.matchMedia('(max-width: 1024px)').matches) {
      return Number.parseInt(carousel.dataset.slidesTablet || '2', 10);
    }

    return Number.parseInt(carousel.dataset.slidesDesktop || '3', 10);
  };

  const renderDots = () => {
    if (!dots) {
      return;
    }

    if ((carousel.dataset.showDots || 'yes') !== 'yes' || totalPages <= 1) {
      dots.replaceChildren();
      dots.hidden = true;
      return;
    }

    dots.hidden = false;
    dots.replaceChildren();

    for (let page = 0; page < totalPages; page += 1) {
      const button = document.createElement('button');
      button.type = 'button';
      button.className = `calio-post-carousel-dot${page === currentPage ? ' is-active' : ''}`;
      button.setAttribute('aria-label', `Go to slide set ${page + 1}`);
      button.dataset.page = String(page);
      dots.appendChild(button);
    }
  };

  const updateState = () => {
    const slidesToShow = Math.max(1, getSlidesToShow());
    const gap = Number.parseFloat(getComputedStyle(track).gap || '0');
    const slideWidth = slides[0]?.getBoundingClientRect().width || 0;
    const maxOffset = Math.max(0, track.scrollWidth - viewport.clientWidth);

    totalPages = getCenterMode()
      ? Math.max(1, slides.length - slidesToShow + 1)
      : Math.max(1, Math.ceil(slides.length / slidesToShow));
    currentPage = Math.min(currentPage, totalPages - 1);
    lastSlidesToShow = slidesToShow;
    carousel.style.setProperty('--calio-carousel-slides', String(slidesToShow));

    if (getCenterMode()) {
      const activeSlideOffset = currentPage * (slideWidth + gap);
      const centeredOffset = activeSlideOffset - (viewport.clientWidth - slideWidth) / 2;
      const clampedOffset = Math.min(Math.max(centeredOffset, 0), maxOffset);
      track.style.transform = `translate3d(-${clampedOffset}px, 0, 0)`;
    } else {
      track.style.transform = `translate3d(-${carousel.clientWidth * currentPage}px, 0, 0)`;
    }

    applyActiveSlides(slidesToShow);

    if (prev) {
      prev.disabled = currentPage === 0 || totalPages === 1;
    }

    if (next) {
      next.disabled = currentPage >= totalPages - 1 || totalPages === 1;
    }

    renderDots();
  };

  const goToPage = (page) => {
    currentPage = Math.min(Math.max(page, 0), totalPages - 1);
    updateState();
  };

  const startAutoplay = (afterInteraction = false) => {
    clearAutoplay();
    clearInteractionTimer();

    if (!getAutoPlayEnabled() || totalPages <= 1) {
      return;
    }

    const startTimer = () => {
      autoplayTimer = window.setInterval(() => {
        currentPage = currentPage >= totalPages - 1 ? 0 : currentPage + 1;
        updateState();
      }, Math.max(1500, getAutoPlaySpeed()));
    };

    if (afterInteraction && getPauseOnInteraction()) {
      interactionTimer = window.setTimeout(startTimer, Math.max(2000, getAutoPlaySpeed()));
      return;
    }

    startTimer();
  };

  prev?.addEventListener('click', () => {
    goToPage(currentPage - 1);
    startAutoplay(true);
  });

  next?.addEventListener('click', () => {
    goToPage(currentPage + 1);
    startAutoplay(true);
  });

  dots?.addEventListener('click', (event) => {
    const target = event.target;
    if (!(target instanceof HTMLButtonElement) || !target.dataset.page) {
      return;
    }

    goToPage(Number.parseInt(target.dataset.page, 10));
    startAutoplay(true);
  });

  viewport?.addEventListener('pointerdown', (event) => {
    isPointerDown = true;
    pointerStartX = event.clientX;
    pointerDeltaX = 0;
    viewport.setPointerCapture?.(event.pointerId);
    carousel.classList.add('is-dragging');
    clearAutoplay();
  });

  viewport?.addEventListener('pointermove', (event) => {
    if (!isPointerDown) {
      return;
    }

    pointerDeltaX = event.clientX - pointerStartX;
  });

  const finishDrag = () => {
    if (!isPointerDown) {
      return;
    }

    isPointerDown = false;
    carousel.classList.remove('is-dragging');

    if (Math.abs(pointerDeltaX) > 50) {
      goToPage(pointerDeltaX < 0 ? currentPage + 1 : currentPage - 1);
    } else {
      updateState();
    }

    startAutoplay(true);
  };

  viewport?.addEventListener('pointerup', finishDrag);
  viewport?.addEventListener('pointercancel', finishDrag);
  viewport?.addEventListener('pointerleave', () => {
    if (isPointerDown) {
      finishDrag();
    }
  });

  if ((carousel.dataset.pauseOnHover || 'yes') === 'yes') {
    carousel.addEventListener('mouseenter', () => {
      clearAutoplay();
      clearInteractionTimer();
    });
    carousel.addEventListener('mouseleave', startAutoplay);
  }

  window.addEventListener('resize', () => {
    const slidesToShow = Math.max(1, getSlidesToShow());
    if (slidesToShow !== lastSlidesToShow) {
      currentPage = 0;
    }
    updateState();
  }, { passive: true });
  updateState();
  startAutoplay();
};

const initPostCarouselScope = (scope = document) => {
  const root = scope instanceof HTMLElement || scope instanceof Document ? scope : document;
  root.querySelectorAll('.calio-post-carousel').forEach(initPostCarousel);
};

document.addEventListener('DOMContentLoaded', () => {
  initPostCarouselScope(document);
});

let calioPostCarouselHookBound = false;
const bindElementorPostCarousel = () => {
  if (calioPostCarouselHookBound) {
    return true;
  }

  if (!window.elementorFrontend?.hooks) {
    return false;
  }

  window.elementorFrontend.hooks.addAction('frontend/element_ready/calio-post-carousel.default', ($scope) => {
    const root = $scope?.[0] || document;
    initPostCarouselScope(root);
  });

  calioPostCarouselHookBound = true;
  return true;
};

window.addEventListener('elementor/frontend/init', bindElementorPostCarousel);
if (!bindElementorPostCarousel()) {
  let attempts = 0;
  const timer = window.setInterval(() => {
    attempts += 1;
    if (bindElementorPostCarousel() || attempts >= 40) {
      window.clearInterval(timer);
    }
  }, 250);
}
