import './style.css';

const toNumber = (value, fallback = 0) => {
  const parsed = Number.parseInt(String(value), 10);
  return Number.isFinite(parsed) ? parsed : fallback;
};

const isEnabled = (value) => value === 'yes' || value === true || value === 'true' || value === '1';
const focusableSelector = [
  'a[href]',
  'button:not([disabled])',
  'input:not([disabled]):not([type="hidden"])',
  'select:not([disabled])',
  'textarea:not([disabled])',
  '[tabindex]:not([tabindex="-1"])',
].join(',');
const isVisible = (element) =>
  !!(element.offsetWidth || element.offsetHeight || element.getClientRects().length);

const bindHoverTriggerMode = (slider) => {
  if (slider.__calioHoverTriggerBound) {
    return;
  }

  if (slider.dataset.hoverTrigger !== 'slider') {
    return;
  }

  const arrowsHover = isEnabled(slider.dataset.arrowsHover);
  const dotsHover = isEnabled(slider.dataset.dotsHover);
  if (!arrowsHover && !dotsHover) {
    return;
  }

  const regions = [
    slider.querySelector('.calio-team-slider-swiper'),
    ...Array.from(slider.querySelectorAll('.calio-team-slider-controls')),
  ].filter((node) => node instanceof Element);

  if (!regions.length) {
    return;
  }

  slider.__calioHoverTriggerBound = true;
  let hoverCount = 0;
  let hideTimer = null;

  const showHoverState = () => {
    if (hideTimer !== null) {
      window.clearTimeout(hideTimer);
      hideTimer = null;
    }
    slider.classList.add('is-hover-active');
  };

  const scheduleHide = () => {
    if (hideTimer !== null) {
      window.clearTimeout(hideTimer);
    }
    hideTimer = window.setTimeout(() => {
      if (hoverCount <= 0) {
        slider.classList.remove('is-hover-active');
      }
    }, 45);
  };

  const handleEnter = () => {
    hoverCount += 1;
    showHoverState();
  };

  const handleLeave = () => {
    hoverCount = Math.max(0, hoverCount - 1);
    scheduleHide();
  };

  regions.forEach((region) => {
    region.addEventListener('mouseenter', handleEnter);
    region.addEventListener('mouseleave', handleLeave);
  });

  slider.addEventListener('mouseleave', () => {
    hoverCount = 0;
    scheduleHide();
  });
};

const bindModalInteractions = (slider) => {
  if (slider.__calioModalBound || !isEnabled(slider.dataset.popupEnabled)) {
    return;
  }

  slider.__calioModalBound = true;
  const closeOnOverlay = isEnabled(slider.dataset.popupCloseOverlay);
  const closeOnEsc = isEnabled(slider.dataset.popupCloseEsc);
  const pauseSliderOnPopup = isEnabled(slider.dataset.popupPauseSlider);

  const getSliderAutoplay = () => slider.__calioTeamSlider?.autoplay;
  const stopSliderAutoplay = () => {
    if (!pauseSliderOnPopup) {
      return;
    }

    const autoplay = getSliderAutoplay();
    if (!autoplay || typeof autoplay.stop !== 'function') {
      return;
    }

    slider.__calioAutoplayWasRunning = autoplay.running === true;
    autoplay.stop();
  };
  const resumeSliderAutoplay = () => {
    if (!pauseSliderOnPopup) {
      return;
    }

    const autoplay = getSliderAutoplay();
    if (!autoplay || typeof autoplay.start !== 'function') {
      return;
    }

    if (slider.__calioAutoplayWasRunning) {
      autoplay.start();
    }
    slider.__calioAutoplayWasRunning = false;
  };

  const getModalById = (id) =>
    slider.querySelector(`.calio-team-slider-modal[data-calio-modal-id="${id}"]`);
  const getModalList = () =>
    Array.from(slider.querySelectorAll('.calio-team-slider-modal[data-calio-modal-id]'));
  const getOpenModal = () =>
    slider.querySelector('.calio-team-slider-modal.is-open');

  const getPanelAndFocusable = (modal) => {
    const panel = modal?.querySelector('.calio-team-slider-modal-panel');
    if (!(panel instanceof HTMLElement)) {
      return { panel: null, focusable: [] };
    }

    const focusable = Array.from(panel.querySelectorAll(focusableSelector)).filter(
      (element) => element instanceof HTMLElement && isVisible(element),
    );

    return { panel, focusable };
  };

  const updateBodyLock = () => {
    const openModalExists = document.querySelector('.calio-team-slider-modal.is-open');
    const method = openModalExists ? 'add' : 'remove';
    document.documentElement.classList[method]('calio-team-slider-modal-open');
    document.body.classList[method]('calio-team-slider-modal-open');
  };

  const closeModal = (modal, options = {}) => {
    const { restoreFocus = true } = options;
    if (!modal) {
      return;
    }

    modal.classList.remove('is-ready');
    modal.classList.remove('is-open');
    modal.setAttribute('aria-hidden', 'true');
    if (!getOpenModal()) {
      resumeSliderAutoplay();
    }
    updateBodyLock();

    if (restoreFocus && modal.__calioOpener instanceof HTMLElement) {
      modal.__calioOpener.focus({ preventScroll: true });
    }
  };

  const closeAllModals = (options = {}) => {
    const { restoreFocus = false } = options;
    getModalList().forEach((modal) => {
      closeModal(modal, { restoreFocus });
    });
    updateBodyLock();
  };

  const openModalElement = (modal, opener = null) => {
    if (!modal) {
      return;
    }

    closeAllModals({ restoreFocus: false });
    stopSliderAutoplay();
    if (opener instanceof HTMLElement) {
      modal.__calioOpener = opener;
    }
    modal.classList.add('is-open');
    modal.setAttribute('aria-hidden', 'false');
    updateBodyLock();

    window.requestAnimationFrame(() => {
      modal.classList.add('is-ready');
      const { panel, focusable } = getPanelAndFocusable(modal);
      const first = focusable[0] || panel;
      if (first instanceof HTMLElement) {
        first.focus({ preventScroll: true });
      }
    });
  };

  const openModal = (id, opener = null) => {
    const modal = getModalById(id);
    openModalElement(modal, opener);
  };

  const openAdjacentModal = (step) => {
    const modals = getModalList();
    if (!modals.length) {
      return;
    }

    const openModalNode = getOpenModal();
    const currentListIndex = modals.indexOf(openModalNode);
    const safeIndex = currentListIndex < 0 ? 0 : currentListIndex;
    const nextIndex = (safeIndex + step + modals.length) % modals.length;
    const opener =
      openModalNode && openModalNode.__calioOpener instanceof HTMLElement
        ? openModalNode.__calioOpener
        : null;
    openModalElement(modals[nextIndex], opener);
  };

  const trapFocus = (event, modal) => {
    const { panel, focusable } = getPanelAndFocusable(modal);
    if (!panel) {
      return;
    }

    if (!focusable.length) {
      event.preventDefault();
      panel.focus({ preventScroll: true });
      return;
    }

    const first = focusable[0];
    const last = focusable[focusable.length - 1];
    const active = document.activeElement;

    if (event.shiftKey && active === first) {
      event.preventDefault();
      last.focus({ preventScroll: true });
      return;
    }

    if (!event.shiftKey && active === last) {
      event.preventDefault();
      first.focus({ preventScroll: true });
    }
  };

  slider.addEventListener('click', (event) => {
    const target = event.target;
    if (!(target instanceof Element)) {
      return;
    }

    const closeButton = target.closest('[data-calio-modal-close]');
    if (closeButton) {
      event.preventDefault();
      const modal = closeButton.closest('.calio-team-slider-modal');
      if (modal instanceof Element) {
        closeModal(modal, { restoreFocus: true });
      }
      return;
    }

    const prevButton = target.closest('[data-calio-modal-prev]');
    if (prevButton) {
      event.preventDefault();
      openAdjacentModal(-1);
      return;
    }

    const nextButton = target.closest('[data-calio-modal-next]');
    if (nextButton) {
      event.preventDefault();
      openAdjacentModal(1);
      return;
    }

    const trigger = target.closest('[data-calio-modal-target]');
    if (trigger && slider.contains(trigger)) {
      if (trigger.classList.contains('has-popup-card-trigger')) {
        const interactiveTarget = target.closest('a,button,input,textarea,select,label');
        if (interactiveTarget && interactiveTarget !== trigger) {
          return;
        }
      }

      const modalId = trigger.getAttribute('data-calio-modal-target');
      if (modalId) {
        event.preventDefault();
        openModal(modalId, trigger instanceof HTMLElement ? trigger : null);
      }
      return;
    }

    const modalBackdrop = target.closest('.calio-team-slider-modal');
    if (closeOnOverlay && modalBackdrop instanceof Element && target === modalBackdrop) {
      closeModal(modalBackdrop, { restoreFocus: true });
    }
  });

  let swipeStartX = 0;
  let swipeStartY = 0;
  let swipePointerId = null;

  slider.addEventListener('pointerdown', (event) => {
    const openModalNode = getOpenModal();
    if (!openModalNode) {
      return;
    }

    if (event.pointerType === 'mouse') {
      return;
    }

    const panel = openModalNode.querySelector('.calio-team-slider-modal-panel');
    if (!(panel instanceof Element) || !panel.contains(event.target)) {
      return;
    }

    const ignoreTarget = event.target instanceof Element
      ? event.target.closest('a,button,input,textarea,select,label')
      : null;
    if (ignoreTarget) {
      return;
    }

    swipeStartX = event.clientX;
    swipeStartY = event.clientY;
    swipePointerId = event.pointerId;
  });

  slider.addEventListener('pointerup', (event) => {
    if (swipePointerId === null || event.pointerId !== swipePointerId) {
      return;
    }

    const deltaX = event.clientX - swipeStartX;
    const deltaY = event.clientY - swipeStartY;
    swipePointerId = null;

    if (Math.abs(deltaX) < 70 || Math.abs(deltaX) < Math.abs(deltaY) + 20) {
      return;
    }

    openAdjacentModal(deltaX < 0 ? 1 : -1);
  });

  slider.addEventListener('keydown', (event) => {
    const target = event.target;
    if (!(target instanceof Element)) {
      return;
    }

    const openModalNode = getOpenModal();
    if (openModalNode) {
      if (event.key === 'Escape' && closeOnEsc) {
        event.preventDefault();
        closeModal(openModalNode, { restoreFocus: true });
        return;
      }

      if (event.key === 'ArrowLeft') {
        event.preventDefault();
        openAdjacentModal(-1);
        return;
      }

      if (event.key === 'ArrowRight') {
        event.preventDefault();
        openAdjacentModal(1);
        return;
      }

      if (event.key === 'Tab') {
        trapFocus(event, openModalNode);
      }
      return;
    }

    const trigger = target.closest('.calio-team-slider-card.has-popup-card-trigger[data-calio-modal-target]');
    if (!trigger || !slider.contains(trigger)) {
      return;
    }

    if (event.key === 'Enter' || event.key === ' ') {
      const modalId = trigger.getAttribute('data-calio-modal-target');
      if (!modalId) {
        return;
      }
      event.preventDefault();
      openModal(modalId, trigger instanceof HTMLElement ? trigger : null);
    }
  });
};

const initTeamSlider = (root) => {
  root.querySelectorAll('.calio-team-slider').forEach((slider) => {
    const swiperElement = slider.querySelector('.calio-team-slider-swiper');
    if (!swiperElement || typeof window.Swiper !== 'function') {
      return;
    }

    if (slider.__calioTeamSlider && typeof slider.__calioTeamSlider.destroy === 'function') {
      slider.__calioTeamSlider.destroy(true, true);
      slider.__calioTeamSlider = null;
    }

    const spaceBetween = toNumber(slider.dataset.spaceBetween, 24);
    const slidesDesktop = Math.max(1, toNumber(slider.dataset.slidesDesktop, 3));
    const slidesTablet = Math.max(1, toNumber(slider.dataset.slidesTablet, 2));
    const slidesMobile = Math.max(1, toNumber(slider.dataset.slidesMobile, 1));
    const slidesScroll = Math.max(1, toNumber(slider.dataset.slidesScroll, 1));
    const speed = Math.max(100, toNumber(slider.dataset.transitionSpeed, 600));
    const autoplaySpeed = Math.max(1000, toNumber(slider.dataset.autoplaySpeed, 3200));

    const showArrows = isEnabled(slider.dataset.showArrows);
    const showDots = isEnabled(slider.dataset.showDots);
    const autoplay = isEnabled(slider.dataset.autoplay);
    const pauseOnHover = isEnabled(slider.dataset.pauseOnHover);
    const pauseOnInteraction = isEnabled(slider.dataset.pauseOnInteraction);
    const loop = isEnabled(slider.dataset.loop);
    const grabCursor = isEnabled(slider.dataset.grabCursor);
    const centeredSlides = isEnabled(slider.dataset.centeredSlides);
    const highlightActive = isEnabled(slider.dataset.highlightActive);

    const prev = showArrows ? slider.querySelector('.calio-team-slider-arrow.is-prev') : null;
    const next = showArrows ? slider.querySelector('.calio-team-slider-arrow.is-next') : null;
    const pagination = showDots ? slider.querySelector('.calio-team-slider-pagination') : null;

    const syncActiveSlide = (swiper) => {
      if (!highlightActive) {
        swiper.slides.forEach((slide) => slide.classList.remove('is-active-slide'));
        return;
      }

      swiper.slides.forEach((slide) => slide.classList.remove('is-active-slide'));

      const active = swiper.slides?.[swiper.activeIndex];
      if (active) {
        active.classList.add('is-active-slide');
      }
    };

    const instance = new window.Swiper(swiperElement, {
      observer: true,
      observeParents: true,
      watchOverflow: true,
      loop,
      speed,
      grabCursor,
      centeredSlides,
      spaceBetween,
      slidesPerView: slidesDesktop,
      slidesPerGroup: slidesScroll,
      autoplay: autoplay
        ? {
            delay: autoplaySpeed,
            disableOnInteraction: pauseOnInteraction,
            pauseOnMouseEnter: pauseOnHover,
          }
        : false,
      navigation: prev && next ? { prevEl: prev, nextEl: next } : false,
      pagination: pagination
        ? {
            el: pagination,
            clickable: true,
          }
        : false,
      breakpoints: {
        0: {
          slidesPerView: slidesMobile,
          slidesPerGroup: 1,
        },
        768: {
          slidesPerView: slidesTablet,
          slidesPerGroup: Math.min(slidesScroll, slidesTablet),
        },
        1025: {
          slidesPerView: slidesDesktop,
          slidesPerGroup: Math.min(slidesScroll, slidesDesktop),
        },
      },
      on: {
        init(swiper) {
          syncActiveSlide(swiper);
        },
        slideChange(swiper) {
          syncActiveSlide(swiper);
        },
        resize(swiper) {
          syncActiveSlide(swiper);
        },
      },
    });

    syncActiveSlide(instance);
    slider.__calioTeamSlider = instance;
    bindHoverTriggerMode(slider);
    bindModalInteractions(slider);
  });
};

const boot = (scope = document) => {
  initTeamSlider(scope);
};

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

let calioTeamSliderHookBound = false;
const bindElementorTeamSlider = () => {
  if (calioTeamSliderHookBound) {
    return true;
  }

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

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

  calioTeamSliderHookBound = true;
  return true;
};

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