/**
 * Configuración global del curso.
 * @namespace
 * @property {string} COURSE_CONFIG_URL - Ruta al archivo de configuración JSON del curso.
 * @property {boolean} DEBUG - Habilita/deshabilita el modo de depuración.
 */
window.COURSE_CONFIG = {
  COURSE_CONFIG_URL: 'config.json',
  DEBUG: false,
  SHOW_PAGINATION: false, // Bandera para mostrar/ocultar paginación
  SHOW_TITLE: false, // Bandera para mostrar/ocultar título
  SHOW_GLOSSARY: false, // Bandera para mostrar/ocultar glosario
};

/**
 * Maneja la lógica del glosario para un botón específico
 * @param {HTMLElement} button - El botón del glosario
 */
async function handleGlossaryButton(button) {
  const offcanvasEl = document.getElementById('offcanvasGlossary');
  if (!offcanvasEl) {
    console.error('Elemento offcanvasGlossary no encontrado');
    return;
  }

  const offcanvas = new bootstrap.Offcanvas(offcanvasEl);

  try {
    const res = await fetch('manual_pld_ft.html');
    if (!res.ok) throw new Error('Error al cargar el glosario');

    const text = await res.text();
    const parser = new DOMParser();
    const doc = parser.parseFromString(text, 'text/html');
    const main = doc.querySelector('main');

    offcanvasEl.querySelector('.offcanvas-body').innerHTML = main
      ? main.innerHTML
      : '<p class="text-danger">No se encontró el contenido.</p>';

    const item = CourseNav.getCurrentSlide();
    const tituloActual = item.title;

    offcanvasEl.querySelectorAll('section[data-title]').forEach((seccion) => {
      seccion.classList.toggle('d-none', seccion.dataset.title !== tituloActual);
    });

    offcanvas.show();
  } catch (err) {
    console.error('Error en glosario:', err);
    offcanvasEl.querySelector('.offcanvas-body').innerHTML =
      '<p class="text-danger">Error al cargar el glosario. Recargue la página e intente nuevamente.</p>';
    offcanvas.show();
  }
}

/**
 * Configura los event listeners para el glosario
 */
function setupGlossaryListeners() {
  // Event delegation para manejar clicks en cualquier botón con la clase 'btn-glossary'
  document.body.addEventListener('click', function (e) {
    const glossaryBtn = e.target.closest('.btn-glossary');
    if (glossaryBtn) {
      e.preventDefault();
      handleGlossaryButton(glossaryBtn);
    }
  });
}
/**
 * Navega a una sección específica, la muestra y hace scroll hacia ella.
 * @function gotoSection
 * @param {string|number} sectionId - ID de la sección (con o sin #) o número de sección.
 * @param {Object} [options={}] - Opciones de scroll.
 * @param {string} [options.behavior="smooth"] - Comportamiento del scroll ('auto' o 'smooth').
 * @param {string} [options.block="start"] - Alineación vertical ('start', 'center', 'end' o 'nearest').
 * @example
 * // Ejemplos de uso:
 * gotoSection('sec1'); // Va a #sec1
 * gotoSection('#sec2'); // Va a #sec2
 * gotoSection(3); // Va a #sec3
 */
function gotoSection(sectionId, options = {}) {
  const defaults = { behavior: 'smooth', block: 'start' };
  const opts = Object.assign(defaults, options);

  // Normalizar el ID de la sección
  let targetId = sectionId;
  if (typeof sectionId === 'number') {
    targetId = `sec${sectionId}`;
  } else if (typeof sectionId === 'string' && !sectionId.startsWith('#')) {
    targetId = sectionId.startsWith('sec') ? sectionId : `sec${sectionId}`;
  } else if (sectionId.startsWith('#')) {
    targetId = sectionId.substring(1);
  }

  const targetElement = document.getElementById(targetId);
  if (targetElement) {
    // Mostrar la sección si está oculta
    if (targetElement.style.display === 'none') {
      targetElement.style.display = '';
    }
    // Hacer scroll hacia la sección
    targetElement.scrollIntoView(opts);
    return true;
  }
  console.warn(`Sección ${targetId} no encontrada`);
  return false;
}

/**
 * Desplaza la ventana hasta la parte superior de un elemento.
 * @function scrollToElementTop
 * @param {string} selector - Selector CSS del elemento objetivo.
 * @param {Object} [options={}] - Opciones de scroll.
 * @param {string} [options.behavior="smooth"] - Comportamiento del scroll ('auto' o 'smooth').
 * @param {string} [options.block="start"] - Alineación vertical ('start', 'center', 'end' o 'nearest').
 * @param {string} [options.inline="nearest"] - Alineación horizontal ('start', 'center', 'end' o 'nearest').
 * @example
 * // Ejemplo de uso:
 * scrollToElementTop('#main-content', { behavior: 'smooth', block: 'start' });
 */
function scrollToElementTop(selector, options = {}) {
  const defaults = { behavior: 'smooth', block: 'start', inline: 'nearest' };
  const opts = Object.assign(defaults, options);
  const el = document.querySelector(selector);
  if (el) el.scrollIntoView(opts);
}
/**
 * Observador de intersección para animar elementos cuando son visibles en el viewport.
 * @function animateOnScroll
 * @param {string} selector - Selector de los elementos a observar.
 * @param {string} animationClass - Clase de animación de Animate.css (ej. 'animate__fadeInUp').
 * @param {Object} [options={}] - Opciones de configuración.
 * @param {number} [options.threshold=0.1] - Umbral de visibilidad (0-1).
 * @param {boolean} [options.animateOnce=true] - Si es true, la animación solo se ejecuta una vez.
 * @param {string} [options.prefix='animate__animated'] - Prefijo para clases de animación.
 * @returns {IntersectionObserver} Instancia del observador.
 * @example
 * // Ejemplo de uso:
 * animateOnScroll('.animar', 'animate__fadeIn', { threshold: 0.2 });
 */
function animateOnScroll(selector, animationClass, options = {}) {
  const { threshold = 0.1, animateOnce = true, prefix = 'animate__animated' } = options;

  const cb = (entries, observer) => {
    entries.forEach((entry) => {
      if (entry.isIntersecting) {
        entry.target.classList.add(prefix, animationClass);
        if (animateOnce) observer.unobserve(entry.target);
      } else if (!animateOnce) {
        entry.target.classList.remove(prefix, animationClass);
      }
    });
  };

  const observer = new IntersectionObserver(cb, { threshold });
  document.querySelectorAll(selector).forEach((el) => observer.observe(el));
  return observer;
}

/**
 * Configura los event listeners cuando el DOM está completamente cargado.
 * @event DOMContentLoaded
 */
document.addEventListener('DOMContentLoaded', () => {
  setupGlossaryListeners();

  // Inicializar sal.js
  if (typeof sal !== 'undefined' && document.querySelectorAll('[data-sal]').length > 0) {
    setTimeout(() => {
      document.querySelectorAll('[data-sal]').forEach((el) => (el.style.visibility = 'visible'));
      sal({
        once: false,
        threshold: 0.3,
        duration: 600,
        easing: 'ease-out',
        distance: '50px',
        opacity: 0,
        scale: 0.95,
      });
    }, 200);
  }

  /**
   * Evento antes de cambiar de slide.
   * @event beforeSlideChange
   * @property {Object} detail - Detalles del evento.
   * @property {number} detail.currentIndex - Índice del slide actual.
   * @property {Array} detail.contentArray - Array completo de contenido.
   */
  document.body.addEventListener('beforeSlideChange', (e) => {
    // console.log("Antes de cambiar de slide:", e.detail);
  });

  /**
   * Evento al cambiar de slide.
   * @event slideChange
   * @property {Object} detail - Detalles del evento.
   * @property {number} detail.slideIndex - Índice del nuevo slide.
   * @property {Array} detail.contentArray - Array completo de contenido.
   */
  document.body.addEventListener('slideChange', (e) => {
    if (e.detail && typeof e.detail.slideIndex === 'number' && Array.isArray(e.detail.contentArray)) {
      console.log(e.detail.contentArray[e.detail.slideIndex].content);

      // Inicializar sal.js si hay elementos con data-sal
      if (typeof sal !== 'undefined' && document.querySelectorAll('[data-sal]').length > 0) {
        setTimeout(() => {
          document.querySelectorAll('[data-sal]').forEach((el) => (el.style.visibility = 'visible'));
          sal({
            once: false,
            threshold: 0.3,
            duration: 600,
            easing: 'ease-out',
            distance: '50px',
            opacity: 0,
            scale: 0.95,
          });
        }, 200);
      }

      // Paginación
      const paginationEl = document.getElementById('pagination');
      const paginacionScoEl = document.querySelector('.paginacion_sco');

      if (window.COURSE_CONFIG.SHOW_PAGINATION) {
        if (paginationEl) {
          paginationEl.innerHTML = e.detail.slideIndex + 1 + ' / ' + e.detail.contentArray.length;
        }
        if (paginacionScoEl) {
          paginacionScoEl.classList.remove('isFalse');
        }
      } else {
        if (paginacionScoEl) {
          paginacionScoEl.classList.add('isFalse');
        }
      }

      // Título de la pantalla actual
      const titleScoEl = document.getElementById('titleSco');
      if (titleScoEl) {
        if (window.COURSE_CONFIG.SHOW_TITLE) {
          titleScoEl.classList.remove('d-none');
          if (e.detail.contentArray[e.detail.slideIndex]) {
            titleScoEl.innerHTML = e.detail.contentArray[e.detail.slideIndex].title || '';
          }
        } else {
          titleScoEl.classList.add('d-none');
        }
      }

      // Glosario
      const btnGlossary = document.getElementById('btn-glossary');
      if (btnGlossary) {
        if (window.COURSE_CONFIG.SHOW_GLOSSARY) {
          const noShowBtnGlossaryIn = [0, 1, e.detail.contentArray.length - 1];
          btnGlossary.style.display = noShowBtnGlossaryIn.includes(e.detail.slideIndex) ? 'none' : 'block';
        } else {
          btnGlossary.style.display = 'none';
        }
      }
    }
  });

  /**
   * Evento al completar un slide.
   * @event slideCompleted
   * @property {Object} detail - Detalles del evento.
   */
  document.body.addEventListener('slideCompleted', (e) => {
    // console.log("Slide completado:", e.detail);
  });

  // Event listener para botón personalizado
  const customButtonEvent = document.getElementById('btn-glossary');
  if (customButtonEvent) {
    customButtonEvent.addEventListener('click', async () => {
      const offcanvasEl = document.getElementById('offcanvasGlossary');
      const offcanvas = new bootstrap.Offcanvas(offcanvasEl);

      try {
        // Carga el HTML completo
        const res = await fetch('manual_pld_ft.html');
        const text = await res.text();

        // Parsea el documento y extrae solo el <main>
        const parser = new DOMParser();
        const doc = parser.parseFromString(text, 'text/html');
        const main = doc.querySelector('main');

        // Inserta el contenido dentro del offcanvas-body
        offcanvasEl.querySelector('.offcanvas-body').innerHTML = main
          ? main.innerHTML
          : '<p class="text-danger">No se encontró el contenido.</p>';

        // **Ocultar todas las secciones del glosario y mostrar sólo la correspondiente**
        const item = CourseNav.getCurrentSlide();
        const tituloActual = item.title;
        console.log('Slide actual:', tituloActual);
        // console.warn(tituloActual);

        // Selecciona únicamente las secciones dentro del offcanvas
        offcanvasEl.querySelectorAll('section[data-title]').forEach((seccion) => {
          if (seccion.dataset.title === tituloActual) {
            seccion.classList.remove('d-none');
          } else {
            seccion.classList.add('d-none');
          }
        });

        // Finalmente, muestra el offcanvas
        offcanvas.show();
      } catch (err) {
        console.error(err);
        offcanvasEl.querySelector('.offcanvas-body').innerHTML =
          '<p class="text-danger">Error al cargar el glosario.</p>';
        offcanvas.show();
      }
    });
  }
});

/**
 * Inicializa un Swiper con opciones personalizadas, reproducción opcional de audio por slide y detección de visita a todos los slides.
 *
 * @param {HTMLElement|string} swiperContainer - Selector CSS o elemento contenedor del Swiper.
 * @param {Function} [callback] - Función que se ejecuta al visitar todos los slides.
 * @param {Object} [options={}] - Opciones personalizadas de inicialización para Swiper (navigation, pagination, etc.).
 * @param {Array} [audios=[]] - Arreglo opcional de objetos Howler (o similar) con audios asignados por slide.
 * @returns {Swiper} - Instancia inicializada de Swiper.
 * @example
 * initializeSwiper('#mySwiper', () => {
 *    console.log('Todos los slides fueron visitados');
 *  }, {
 *    effect: 'flip',
 *    nextSelector: '.custom-next',
 *    prevSelector: '.custom-prev',
 *    paginationSelector: '.custom-pagination',
 *  }, [
 *    new Howl({ src: 'audio1.mp3' }),
 *    null, // Slide sin audio
 *    new Howl({ src: 'audio3.mp3' }),
 *  ]);
 *
 */
function initializeSwiper(swiperContainer, callback, options = {}, audios = [], autoPlaySound = true) {
  const visitedSlides = new Set();
  const container = typeof swiperContainer === 'string' ? document.querySelector(swiperContainer) : swiperContainer;
  const parent = container.parentElement;
  if (options.navigation && options.navigation.nextEl && options.navigation.prevEl) {
    options.navigation.nextEl = container.querySelector(options.navigation.nextEl)
      ? container.querySelector(options.navigation.nextEl)
      : parent.querySelector(options.navigation.nextEl);
    options.navigation.prevEl = container.querySelector(options.navigation.prevEl)
      ? container.querySelector(options.navigation.prevEl)
      : parent.querySelector(options.navigation.prevEl);
  }
  const defaultParams = {
    effect: 'slide',
    loop: false,
    autoHeight: true,
  };

  // Combina opciones personalizadas con las por defecto
  const params = {
    ...defaultParams,
    ...options,
    on: {
      init: function () {
        visitedSlides.add(this.activeIndex);
        if (audios.length > 0 && audios[this.activeIndex] && autoPlaySound) {
          CourseNav.audioController.stopAllSoundsAndPlay(audios[this.activeIndex]);
        }
      },
      slideChange: function () {
        const index = this.activeIndex;
        visitedSlides.add(index);
        if (audios.length > 0) {
          CourseNav.audioController.stopAudio();
        }
        if (audios.length > 0 && audios[index]) {
          CourseNav.audioController.stopAllSoundsAndPlay(audios[index]);
        }
        if (visitedSlides.size === this.slides.length && typeof callback === 'function') {
          callback();
        }
      },
    },
  };
  return new Swiper(container, params);
}
