/**
 * Custom number input stepper buttons.
 *
 * Replaces native browser spinners with consistent, theme-aware custom buttons.
 * Stepper arrows are pure black in light mode and pure white in dark mode.
 * Background remains transparent in all states.
 *
 * @package vareoncalc_Suite_Pro
 */

const STEPPER_WRAPPER_CLASS = 'vareoncalc-stepper';
const STEPPER_BTN_CLASS = 'vareoncalc-stepper__btn';
const STEPPER_ICON_CLASS = 'vareoncalc-stepper__icon';

/**
 * Check if an input already has stepper buttons applied.
 * @param {HTMLInputElement} input
 * @returns {boolean}
 */
function hasSteppers(input) {
  const parent = input.parentElement;
  return parent && parent.classList.contains(STEPPER_WRAPPER_CLASS);
}

/**
 * Create a stepper button element.
 * @param {'up'|'down'} direction
 * @returns {HTMLButtonElement}
 */
function createStepperButton(direction) {
  const btn = document.createElement('button');
  btn.type = 'button';
  btn.className = `${STEPPER_BTN_CLASS} ${STEPPER_BTN_CLASS}--${direction}`;
  btn.setAttribute('aria-label', direction === 'up' ? 'Increase value' : 'Decrease value');
  btn.tabIndex = -1; // Keep focus on input, not buttons

  // SVG arrow icon
  const icon = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
  icon.setAttribute('class', STEPPER_ICON_CLASS);
  icon.setAttribute('width', '10');
  icon.setAttribute('height', '10');
  icon.setAttribute('viewBox', '0 0 10 10');
  icon.setAttribute('fill', 'none');
  icon.setAttribute('stroke', 'currentColor');
  icon.setAttribute('stroke-width', '1.5');
  icon.setAttribute('stroke-linecap', 'round');
  icon.setAttribute('stroke-linejoin', 'round');

  const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
  if (direction === 'up') {
    path.setAttribute('d', 'M2 6.5L5 3.5L8 6.5');
  } else {
    path.setAttribute('d', 'M2 3.5L5 6.5L8 3.5');
  }
  icon.appendChild(path);
  btn.appendChild(icon);

  return btn;
}

/**
 * Dispatch input and change events to trigger auto-calc and other listeners.
 * @param {HTMLInputElement} input
 */
function dispatchInputEvents(input) {
  input.dispatchEvent(new Event('input', { bubbles: true }));
  input.dispatchEvent(new Event('change', { bubbles: true }));
}

/**
 * Apply custom stepper buttons to a single number input.
 * @param {HTMLInputElement} input
 */
function applyStepperToInput(input) {
  if (hasSteppers(input)) {
    return;
  }

  // Skip inputs that explicitly opt out
  if (input.dataset.vareoncalcNoStepper === 'true') {
    return;
  }

  const parent = input.parentElement;
  if (!parent) {
    return;
  }

  // Check if input is inside an InputAdornment wrapper
  const isAdorned = parent.classList.contains('vareoncalc-input-adorned');

  // Create wrapper
  const wrapper = document.createElement('div');
  wrapper.className = STEPPER_WRAPPER_CLASS;

  // If adorned, we need to work within the existing structure
  if (isAdorned) {
    // Insert wrapper inside the adorned container, wrapping only the input
    parent.insertBefore(wrapper, input);
    wrapper.appendChild(input);
  } else {
    // Replace input with wrapper containing input
    parent.insertBefore(wrapper, input);
    wrapper.appendChild(input);
  }

  // Create buttons
  const upBtn = createStepperButton('up');
  const downBtn = createStepperButton('down');

  // Button container (stacked vertically)
  const btnContainer = document.createElement('div');
  btnContainer.className = 'vareoncalc-stepper__buttons';
  btnContainer.appendChild(upBtn);
  btnContainer.appendChild(downBtn);

  wrapper.appendChild(btnContainer);

  // Event handlers
  upBtn.addEventListener('click', (e) => {
    e.preventDefault();
    e.stopPropagation();
    const step = parseFloat(input.step) || 1;
    const currentVal = parseFloat(input.value) || 0;
    const max = input.max !== '' ? parseFloat(input.max) : Infinity;
    const newVal = Math.min(currentVal + step, max);
    input.value = newVal;
    dispatchInputEvents(input);
    input.focus();
  });

  downBtn.addEventListener('click', (e) => {
    e.preventDefault();
    e.stopPropagation();
    const step = parseFloat(input.step) || 1;
    const currentVal = parseFloat(input.value) || 0;
    const min = input.min !== '' ? parseFloat(input.min) : -Infinity;
    const newVal = Math.max(currentVal - step, min);
    input.value = newVal;
    dispatchInputEvents(input);
    input.focus();
  });

  // Keyboard support: allow arrow keys on buttons to step
  const handleKeydown = (e) => {
    const step = parseFloat(input.step) || 1;
    const currentVal = parseFloat(input.value) || 0;
    if (e.key === 'ArrowUp') {
      e.preventDefault();
      const max = input.max !== '' ? parseFloat(input.max) : Infinity;
      input.value = Math.min(currentVal + step, max);
      dispatchInputEvents(input);
    } else if (e.key === 'ArrowDown') {
      e.preventDefault();
      const min = input.min !== '' ? parseFloat(input.min) : -Infinity;
      input.value = Math.max(currentVal - step, min);
      dispatchInputEvents(input);
    }
  };

  upBtn.addEventListener('keydown', handleKeydown);
  downBtn.addEventListener('keydown', handleKeydown);
}

/**
 * Apply custom stepper buttons to all number inputs within a container.
 * @param {HTMLElement} container
 */
export function applyNumberSteppers(container) {
  if (!container) {
    return;
  }

  const numberInputs = container.querySelectorAll('input[type="number"]');
  numberInputs.forEach(applyStepperToInput);
}

/**
 * Create a MutationObserver to apply steppers to dynamically added number inputs.
 * @param {HTMLElement} container - The calculator root element to observe.
 * @returns {MutationObserver|null} The observer instance, or null if not supported.
 */
export function observeNumberInputs(container) {
  if (!container || typeof MutationObserver === 'undefined') {
    return null;
  }

  const observer = new MutationObserver((mutations) => {
    for (const mutation of mutations) {
      if (mutation.type === 'childList') {
        mutation.addedNodes.forEach((node) => {
          if (node.nodeType !== Node.ELEMENT_NODE) {
            return;
          }

          // Check if the added node is a number input
          if (node.tagName === 'INPUT' && node.type === 'number') {
            applyStepperToInput(node);
          }

          // Check for number inputs within the added node
          if (typeof node.querySelectorAll === 'function') {
            const inputs = node.querySelectorAll('input[type="number"]');
            inputs.forEach(applyStepperToInput);
          }
        });
      }
    }
  });

  observer.observe(container, {
    childList: true,
    subtree: true
  });

  return observer;
}

