import './style.css';

const isEnabled = (value) => value === 'yes' || value === true || value === 'true' || value === '1';
const toNumber = (value, fallback = 0) => {
  const parsed = Number.parseFloat(String(value));
  return Number.isFinite(parsed) ? parsed : fallback;
};

const getSwiperConstructor = () => {
  if (typeof window.Swiper === 'function') {
    return window.Swiper;
  }

  if (typeof window.Swiper?.default === 'function') {
    return window.Swiper.default;
  }

  return null;
};

const getMotionFromVars = (effect) => {
  switch (effect) {
    case 'scale-in':
      return { opacity: 0, scale: 0.88 };
    case 'slide-left':
      return { opacity: 0, x: -36 };
    case 'slide-right':
      return { opacity: 0, x: 36 };
    case 'blur-up':
      return { opacity: 0, y: 24, filter: 'blur(12px)' };
    case 'fade-up':
    default:
      return { opacity: 0, y: 28 };
  }
};

const splitSelectorMap = {
  badge: '.calio-cube-split-target-badge',
  eyebrow: '.calio-cube-split-target-eyebrow',
  title: '.calio-cube-split-target-title',
  description: '.calio-cube-split-target-description',
  button: '.calio-cube-split-target-button',
};

const normalizeSplitTargets = (slider) => String(slider.dataset.splitTargets || 'title')
  .split(',')
  .map((target) => target.trim())
  .filter(Boolean);

const getSplitTargetElements = (slider, activeSlide) => {
  if (!isEnabled(slider.dataset.splitEnabled) || !activeSlide) {
    return [];
  }

  return normalizeSplitTargets(slider).flatMap((target) => {
    const selector = splitSelectorMap[target];
    return selector ? Array.from(activeSlide.querySelectorAll(selector)) : [];
  });
};

const cleanupTextSegments = (slider) => {
  if (!Array.isArray(slider.__calioCubeTextSegments)) {
    slider.__calioCubeTextSegments = [];
    return;
  }

  slider.__calioCubeTextSegments.forEach((segment) => {
    if (typeof segment?.revert === 'function') {
      segment.revert();
    }
  });
  slider.__calioCubeTextSegments = [];
};

const getSplitHost = (element) => element.querySelector?.('a') || element;

const createNativeSplit = (element, type) => {
  const host = getSplitHost(element);
  const originalNodes = Array.from(host.childNodes).map((node) => node.cloneNode(true));
  const text = host.textContent || '';
  const split = {
    chars: [],
    words: [],
    lines: [],
    revert: () => {
      host.replaceChildren(...originalNodes.map((node) => node.cloneNode(true)));
      host.removeAttribute('aria-label');
    },
  };

  host.setAttribute('aria-label', text);
  host.textContent = '';

  if (type === 'lines') {
    const line = document.createElement('span');
    line.className = 'calio-split-text-unit calio-split-text-line';
    line.setAttribute('aria-hidden', 'true');
    line.textContent = text;
    host.appendChild(line);
    split.lines.push(line);
    return split;
  }

  const words = text.split(/(\s+)/);
  words.forEach((word) => {
    if (/^\s+$/.test(word)) {
      host.appendChild(document.createTextNode(word));
      return;
    }

    if (type === 'chars' || type === 'words-chars') {
      const wordWrap = document.createElement('span');
      wordWrap.className = 'calio-split-text-word';
      wordWrap.setAttribute('aria-hidden', 'true');
      Array.from(word).forEach((char) => {
        const charWrap = document.createElement('span');
        charWrap.className = 'calio-split-text-unit calio-split-text-char';
        charWrap.textContent = char;
        wordWrap.appendChild(charWrap);
        split.chars.push(charWrap);
      });
      host.appendChild(wordWrap);
      split.words.push(wordWrap);
      return;
    }

    const wordWrap = document.createElement('span');
    wordWrap.className = 'calio-split-text-unit calio-split-text-word';
    wordWrap.setAttribute('aria-hidden', 'true');
    wordWrap.textContent = word;
    host.appendChild(wordWrap);
    split.words.push(wordWrap);
  });

  return split;
};

const createSplit = (element, slider) => {
  const requestedType = slider.dataset.splitType || 'words';
  return createNativeSplit(element, requestedType);
};

const getSplitUnits = (split, type) => {
  if (type === 'chars' || type === 'words-chars') {
    return split.chars || [];
  }

  if (type === 'lines') {
    return split.lines || [];
  }

  return split.words || [];
};

const getSplitFromVars = (effect) => {
  switch (effect) {
    case 'blur':
      return { opacity: 0, y: '0.7em', filter: 'blur(10px)' };
    case 'scale':
      return { opacity: 0, y: '0.2em', scale: 0.82 };
    case 'rotate':
      return { opacity: 0, y: '0.8em', rotateX: -65, transformOrigin: '50% 100%' };
    case 'rise':
    default:
      return { opacity: 0, y: '0.85em' };
  }
};

const toTransform = (vars = {}) => {
  const parts = [];
  if (vars.x !== undefined) {
    parts.push(`translateX(${typeof vars.x === 'number' ? `${vars.x}px` : vars.x})`);
  }
  if (vars.y !== undefined) {
    parts.push(`translateY(${typeof vars.y === 'number' ? `${vars.y}px` : vars.y})`);
  }
  if (vars.scale !== undefined) {
    parts.push(`scale(${vars.scale})`);
  }
  if (vars.rotateX !== undefined) {
    parts.push(`rotateX(${typeof vars.rotateX === 'number' ? `${vars.rotateX}deg` : vars.rotateX})`);
  }
  return parts.length ? parts.join(' ') : 'none';
};

const runAnimation = (element, fromVars, options) => {
  if (!element || typeof element.animate !== 'function') {
    element?.classList?.add('is-motion-ready');
    return null;
  }

  if (element.__calioCubeAnimation && typeof element.__calioCubeAnimation.cancel === 'function') {
    element.__calioCubeAnimation.cancel();
  }

  const animation = element.animate(
    [
      {
        opacity: fromVars.opacity ?? 0,
        transform: toTransform(fromVars),
        filter: fromVars.filter || 'none',
        transformOrigin: fromVars.transformOrigin || '50% 50%',
      },
      {
        opacity: 1,
        transform: 'none',
        filter: 'blur(0px)',
        transformOrigin: fromVars.transformOrigin || '50% 50%',
      },
    ],
    {
      duration: options.duration,
      delay: options.delay,
      easing: options.easing,
      fill: 'both',
    },
  );

  element.__calioCubeAnimation = animation;
  animation.finished
    .then(() => {
      if (element.__calioCubeAnimation === animation) {
        element.__calioCubeAnimation = null;
        element.style.opacity = '1';
        element.style.transform = '';
        element.style.filter = '';
      }
    })
    .catch(() => {});
  return animation;
};

const mapEasing = (ease) => {
  switch (ease) {
    case 'power2.out':
      return 'cubic-bezier(0.22, 1, 0.36, 1)';
    case 'power4.out':
    case 'expo.out':
      return 'cubic-bezier(0.16, 1, 0.3, 1)';
    case 'back.out(1.4)':
      return 'cubic-bezier(0.34, 1.56, 0.64, 1)';
    case 'power3.out':
    default:
      return 'cubic-bezier(0.2, 0.8, 0.2, 1)';
  }
};

const animateTextSegments = (slider, activeSlide, baseDelay = 0) => {
  if (!isEnabled(slider.dataset.splitEnabled)) {
    cleanupTextSegments(slider);
    return [];
  }

  const targets = getSplitTargetElements(slider, activeSlide);
  cleanupTextSegments(slider);

  if (!targets.length) {
    return [];
  }

  const type = slider.dataset.splitType || 'words';
  const units = [];
  const splits = targets.map((target) => {
    const split = createSplit(target, slider);
    units.push(...getSplitUnits(split, type));
    return split;
  });

  slider.__calioCubeTextSegments = splits;

  if (!units.length) {
    return targets;
  }

  const fromVars = getSplitFromVars(slider.dataset.splitEffect || 'rise');
  const duration = Math.max(100, toNumber(slider.dataset.splitDuration, 620));
  const stagger = Math.max(0, toNumber(slider.dataset.splitStagger, 34));
  const easing = mapEasing(slider.dataset.motionEase || 'power3.out');
  units.forEach((unit, index) => {
    runAnimation(unit, fromVars, {
      duration,
      delay: Math.max(0, baseDelay * 1000) + (stagger * index),
      easing,
    });
  });

  return targets;
};

const animateActiveSlideItems = (slider, swiper) => {
  const hasItemMotion = isEnabled(slider.dataset.motionEnabled);
  const hasSplitMotion = isEnabled(slider.dataset.splitEnabled);

  if (!hasItemMotion && !hasSplitMotion) {
    cleanupTextSegments(slider);
    return;
  }

  const activeSlide = swiper?.slides?.[swiper.activeIndex];
  const splitTargets = getSplitTargetElements(slider, activeSlide);
  const allItems = activeSlide ? Array.from(activeSlide.querySelectorAll('.calio-cube-animate-item')) : [];
  const splitPriority = slider.dataset.splitPriority || 'split-only';
  const items = hasSplitMotion && splitPriority === 'split-only'
    ? []
    : splitTargets.length
    ? allItems.filter((item) => !splitTargets.some((target) => item === target || item.contains(target) || target.contains(item)))
    : allItems;

  const duration = Math.max(0.1, toNumber(slider.dataset.motionDuration, 650) / 1000);
  const stagger = Math.max(0, toNumber(slider.dataset.motionStagger, 70) / 1000);
  const delay = Math.max(0, toNumber(slider.dataset.motionDelay, 80) / 1000);
  const ease = slider.dataset.motionEase || 'power3.out';
  const fromVars = getMotionFromVars(slider.dataset.motionEffect || 'fade-up');

  slider.classList.remove('is-motion-ready');
  if (hasItemMotion && items.length) {
    items.forEach((item, index) => {
      runAnimation(item, fromVars, {
        duration: Math.round(duration * 1000),
        delay: Math.round((delay + (stagger * index)) * 1000),
        easing: mapEasing(ease),
      });
    });
  }
  animateTextSegments(slider, activeSlide, delay);
  activeSlide?.classList.remove('is-motion-ready');
  window.requestAnimationFrame(() => {
    activeSlide?.classList.add('is-motion-ready');
  });
};

const initCubeSlider = (root = document) => {
  root.querySelectorAll('.calio-cube-slider').forEach((slider) => {
    const swiperElement = slider.querySelector('.calio-cube-slider-swiper');
    const SwiperConstructor = getSwiperConstructor();

    if (!swiperElement || !SwiperConstructor) {
      return;
    }

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

    const prev = slider.querySelector('.calio-cube-slider-arrow.is-prev');
    const next = slider.querySelector('.calio-cube-slider-arrow.is-next');
    const pagination = slider.querySelector('.calio-cube-slider-pagination');
    const autoplay = isEnabled(slider.dataset.autoplay);
    const pauseOnHover = isEnabled(slider.dataset.pauseOnHover);
    const speed = Math.max(150, toNumber(slider.dataset.speed, 850));
    const autoplaySpeed = Math.max(1000, toNumber(slider.dataset.autoplaySpeed, 3600));

    const instance = new SwiperConstructor(swiperElement, {
      effect: 'cube',
      cubeEffect: {
        shadow: isEnabled(slider.dataset.cubeShadow),
        slideShadows: isEnabled(slider.dataset.cubeSlideShadows),
        shadowOffset: Math.max(0, toNumber(slider.dataset.cubeShadowOffset, 28)),
        shadowScale: Math.max(0, toNumber(slider.dataset.cubeShadowScale, 0.82)),
      },
      observer: true,
      observeParents: true,
      watchOverflow: false,
      slidesPerView: 1,
      loop: isEnabled(slider.dataset.loop),
      speed,
      grabCursor: isEnabled(slider.dataset.grabCursor),
      autoplay: autoplay
        ? {
            delay: autoplaySpeed,
            disableOnInteraction: false,
            pauseOnMouseEnter: pauseOnHover,
          }
        : false,
      navigation: prev && next ? { prevEl: prev, nextEl: next } : false,
      pagination: pagination
        ? {
            el: pagination,
            clickable: true,
            type: 'bullets',
            bulletClass: 'swiper-pagination-bullet',
            bulletActiveClass: 'swiper-pagination-bullet-active',
          }
        : false,
      on: {
        init(swiper) {
          slider.classList.add('is-ready');
          swiper.update();
          if (pagination && swiper.pagination) {
            swiper.pagination.render();
            swiper.pagination.update();
          }
          animateActiveSlideItems(slider, swiper);
        },
        slideChangeTransitionStart(swiper) {
          animateActiveSlideItems(slider, swiper);
        },
      },
    });

    animateActiveSlideItems(slider, instance);
    slider.__calioCubeSlider = instance;
  });
};

const bootCubeSlider = (attempt = 0) => {
  if (!getSwiperConstructor() && attempt < 30) {
    window.setTimeout(() => bootCubeSlider(attempt + 1), 120);
    return;
  }

  initCubeSlider(document);
};

if (document.readyState === 'loading') {
  document.addEventListener('DOMContentLoaded', () => bootCubeSlider(), { once: true });
} else {
  window.requestAnimationFrame(() => bootCubeSlider());
}

window.addEventListener('load', () => bootCubeSlider(), { once: true });

let calioCubeSliderHookBound = false;
const bindElementorCubeSlider = () => {
  if (calioCubeSliderHookBound) {
    return true;
  }

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

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

  calioCubeSliderHookBound = true;
  return true;
};

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