/**
 * Componente de modal de confirmación para salir sin guardar cambios
 * @param {Object} options - Opciones del modal
 * @param {string} options.title - Título del modal (opcional)
 * @param {string} options.message - Mensaje del modal (opcional)
 * @param {string} options.confirmText - Texto del botón de confirmar (opcional)
 * @param {string} options.cancelText - Texto del botón de cancelar (opcional)
 * @param {Function} options.onConfirm - Callback al confirmar salida
 * @param {Function} options.onCancel - Callback al cancelar (quedarse)
 * @returns {HTMLElement} El elemento del modal
 */
export function ConfirmExitModal(options = {}) {
  const {
    title = 'Cambios sin guardar',
    message = '¿Estás seguro de que quieres salir? Los cambios no guardados se perderán.',
    confirmText = 'Salir sin guardar',
    cancelText = 'Quedarse',
    onConfirm = () => { },
    onCancel = () => { }
  } = options;

  const modal = document.createElement('div');
  modal.className = 'confirm-exit-overlay';

  modal.innerHTML = /*html*/`
    <div class="confirm-exit-modal">
      <div class="confirm-exit-icon">
        <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
          <path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/>
          <line x1="12" y1="9" x2="12" y2="13"/>
          <line x1="12" y1="17" x2="12.01" y2="17"/>
        </svg>
      </div>
      <h3 class="confirm-exit-title">${title}</h3>
      <p class="confirm-exit-message">${message}</p>
      <div class="confirm-exit-actions">
        <button class="btn-stay" type="button">${cancelText}</button>
        <button class="btn-exit" type="button">${confirmText}</button>
      </div>
    </div>
  `;

  const handleClose = (confirmed) => {
    modal.classList.add('closing');
    setTimeout(() => {
      modal.remove();
      if (confirmed) {
        onConfirm();
      } else {
        onCancel();
      }
    }, 200);
  };

  // Botón quedarse
  modal.querySelector('.btn-stay').addEventListener('click', () => {
    handleClose(false);
  });

  // Botón salir
  modal.querySelector('.btn-exit').addEventListener('click', () => {
    handleClose(true);
  });

  // Cerrar con Escape
  const handleKeyDown = (e) => {
    if (e.key === 'Escape') {
      handleClose(false);
      document.removeEventListener('keydown', handleKeyDown);
    }
  };
  document.addEventListener('keydown', handleKeyDown);

  // Click fuera del modal (quedarse)
  modal.addEventListener('click', (e) => {
    if (e.target === modal) {
      handleClose(false);
    }
  });

  return modal;
}

/**
 * Muestra el modal de confirmación de salida
 * @param {Object} options - Opciones del modal
 * @returns {Promise<boolean>} true si confirma salir, false si cancela
 */
export function showConfirmExitModal(options = {}) {
  return new Promise((resolve) => {
    const modal = ConfirmExitModal({
      ...options,
      onConfirm: () => resolve(true),
      onCancel: () => resolve(false)
    });
    document.body.appendChild(modal);
  });
}

/**
 * Clase para gestionar el seguimiento de cambios en formularios
 */
export class FormChangeTracker {
  constructor() {
    this.initialState = null;
    this.hasChanges = false;
    this.listeners = [];
  }

  /**
   * Captura el estado inicial del formulario
   * @param {HTMLFormElement|HTMLElement} container - Contenedor del formulario
   */
  captureInitialState(container) {
    this.initialState = this.getFormState(container);
    this.hasChanges = false;
  }

  /**
   * Obtiene el estado actual del formulario
   * @param {HTMLFormElement|HTMLElement} container - Contenedor del formulario
   * @returns {Object} Estado del formulario
   */
  getFormState(container) {
    const state = {};

    // Inputs de texto, date, number, etc.
    container.querySelectorAll('input:not([type="button"]):not([type="submit"])').forEach(input => {
      const key = input.name || input.id || input.className;
      if (key) {
        state[`input_${key}`] = input.value;
      }
    });

    // Textareas
    container.querySelectorAll('textarea').forEach(textarea => {
      const key = textarea.name || textarea.id || textarea.className;
      if (key) {
        state[`textarea_${key}`] = textarea.value;
      }
    });

    // Selects
    container.querySelectorAll('select').forEach(select => {
      const key = select.name || select.id || select.className;
      if (key) {
        state[`select_${key}`] = select.value;
      }
    });

    // Contar líneas de factura si existen
    const lines = container.querySelectorAll('.line-row-compact, .invoice-lines tr');
    state['_lineCount'] = lines.length;

    return state;
  }

  /**
   * Verifica si hay cambios comparando con el estado inicial
   * @param {HTMLFormElement|HTMLElement} container - Contenedor del formulario
   * @returns {boolean} true si hay cambios
   */
  checkForChanges(container) {
    if (!this.initialState) return false;

    const currentState = this.getFormState(container);

    // Comparar estados
    const initialKeys = Object.keys(this.initialState);
    const currentKeys = Object.keys(currentState);

    // Si cambiaron las claves, hay cambios
    if (initialKeys.length !== currentKeys.length) {
      this.hasChanges = true;
      return true;
    }

    // Comparar valores
    for (const key of initialKeys) {
      if (this.initialState[key] !== currentState[key]) {
        this.hasChanges = true;
        return true;
      }
    }

    this.hasChanges = false;
    return false;
  }

  /**
   * Configura listeners automáticos para detectar cambios
   * @param {HTMLFormElement|HTMLElement} container - Contenedor del formulario
   */
  setupAutoTracking(container) {
    const checkChanges = () => {
      this.checkForChanges(container);
    };

    // Escuchar cambios en inputs
    container.addEventListener('input', checkChanges);
    container.addEventListener('change', checkChanges);

    // Observar cambios en el DOM (líneas añadidas/eliminadas)
    const observer = new MutationObserver(checkChanges);
    observer.observe(container, { childList: true, subtree: true });

    this.listeners.push({ container, checkChanges, observer });
  }

  /**
   * Marca que se han guardado los cambios
   */
  markAsSaved() {
    this.hasChanges = false;
  }

  /**
   * Limpia los listeners
   */
  cleanup() {
    this.listeners.forEach(({ container, checkChanges, observer }) => {
      container.removeEventListener('input', checkChanges);
      container.removeEventListener('change', checkChanges);
      observer.disconnect();
    });
    this.listeners = [];
  }
}
