/**
 * Measurement utilities for handling imperial/metric conversions.
 */

import { __, sprintf } from '@vareoncalc/calculator-base';

const MILE_TO_KM = 1.60934;
const FOOT_TO_METER = 0.3048;
const INCH_TO_CM = 2.54;
const SQFT_TO_SQM = 0.092903;
const GALLON_TO_LITER = 3.78541;
const LB_TO_KG = 0.45359237;

const STORAGE_KEY = 'vareoncalc_measurement_mode';

/**
 * Saves the user's measurement mode preference to localStorage.
 * @param {string} mode - 'metric' or 'imperial'
 */
function saveMeasurementPreference(mode) {
  if (typeof window === 'undefined' || typeof localStorage === 'undefined') return;
  try {
    localStorage.setItem(STORAGE_KEY, mode);
  } catch (e) {
    // localStorage might be disabled or full
  }
}

/**
 * Retrieves the user's saved measurement mode preference from localStorage.
 * @returns {string|null} The saved mode or null if not set
 */
function getSavedMeasurementPreference() {
  if (typeof window === 'undefined' || typeof localStorage === 'undefined') return null;
  try {
    const saved = localStorage.getItem(STORAGE_KEY);
    if (saved === 'metric' || saved === 'imperial') {
      return saved;
    }
  } catch (e) {
    // localStorage might be disabled
  }
  return null;
}

/**
 * Returns the configured measurement system.
 * Possible values: 'imperial', 'metric', 'mixed'
 */
export function getMeasurementSystem() {
  if (typeof window === 'undefined') {
    return 'mixed';
  }

  // Read directly from VAREONCALC_CFG - this is set by wp_localize_script
  const globalCfg = window.VAREONCALC_CFG;
  if (!globalCfg || !globalCfg.measurement) {
    return 'mixed';
  }

  // Return the system value, defaulting to 'mixed' only if not set
  const system = globalCfg.measurement.system;
  if (system === 'metric' || system === 'imperial' || system === 'mixed') {
    return system;
  }

  return 'mixed';
}

/**
 * Returns true if the system is set to 'mixed', meaning the toggle should be shown.
 */
export function shouldShowMeasurementToggle() {
  return getMeasurementSystem() === 'mixed';
}

/**
 * Returns the preferred measurement mode (imperial/metric) based on the global setting.
 * When system is 'mixed', checks localStorage for user's saved preference first,
 * then falls back to the provided defaultMode (default: 'imperial').
 */
export function getPreferredMeasurementMode(defaultMode = 'imperial') {
  const system = getMeasurementSystem();
  if (system === 'metric') return 'metric';
  if (system === 'imperial') return 'imperial';

  // System is 'mixed' - check for saved user preference
  const savedPreference = getSavedMeasurementPreference();
  if (savedPreference) {
    return savedPreference;
  }

  return defaultMode;
}

/**
 * Creates a measurement toggle button group for switching between metric and imperial.
 * @param {string} currentMode - Current mode ('metric' or 'imperial')
 * @param {Function} onChange - Callback when mode changes, receives new mode as argument
 * @returns {HTMLElement} The toggle container element
 */
export function createMeasurementToggle(currentMode, onChange) {
  const container = document.createElement('div');
  container.className = 'vareoncalc-toggle vareoncalc-measurement-toggle';
  container.dataset.active = currentMode;
  container.dataset.mode = currentMode;
  container.setAttribute('role', 'group');
  container.setAttribute('aria-label', __('Measurement system', 'vareon-calculator-suite-lite'));

  const track = document.createElement('div');
  track.className = 'vareoncalc-toggle__track';

  const metricBtn = document.createElement('button');
  metricBtn.type = 'button';
  metricBtn.className = 'vareoncalc-toggle__option vareoncalc-measurement-toggle__btn vareoncalc-measurement-toggle__btn--metric' + (currentMode === 'metric' ? ' is-active vareoncalc-measurement-toggle__btn--active' : '');
  metricBtn.textContent = __('Metric', 'vareon-calculator-suite-lite');
  metricBtn.setAttribute('aria-pressed', currentMode === 'metric' ? 'true' : 'false');
  metricBtn.dataset.mode = 'metric';

  const imperialBtn = document.createElement('button');
  imperialBtn.type = 'button';
  imperialBtn.className = 'vareoncalc-toggle__option vareoncalc-measurement-toggle__btn vareoncalc-measurement-toggle__btn--imperial' + (currentMode === 'imperial' ? ' is-active vareoncalc-measurement-toggle__btn--active' : '');
  imperialBtn.textContent = __('Imperial', 'vareon-calculator-suite-lite');
  imperialBtn.setAttribute('aria-pressed', currentMode === 'imperial' ? 'true' : 'false');
  imperialBtn.dataset.mode = 'imperial';

  track.appendChild(metricBtn);
  track.appendChild(imperialBtn);
  container.appendChild(track);

  // Handle clicks
  container.addEventListener('click', (e) => {
    const btn = e.target.closest('.vareoncalc-measurement-toggle__btn');
    if (!btn) return;

    const newMode = btn.dataset.mode;
    if (newMode === currentMode) return;

    // Update active states
    metricBtn.classList.toggle('is-active', newMode === 'metric');
    imperialBtn.classList.toggle('is-active', newMode === 'imperial');
    metricBtn.classList.toggle('vareoncalc-measurement-toggle__btn--active', newMode === 'metric');
    imperialBtn.classList.toggle('vareoncalc-measurement-toggle__btn--active', newMode === 'imperial');
    metricBtn.setAttribute('aria-pressed', newMode === 'metric' ? 'true' : 'false');
    imperialBtn.setAttribute('aria-pressed', newMode === 'imperial' ? 'true' : 'false');
    container.dataset.active = newMode;
    container.dataset.mode = newMode;

    // Save preference to localStorage (only effective when system is 'mixed')
    saveMeasurementPreference(newMode);

    // Update internal state and call callback
    currentMode = newMode;
    if (typeof onChange === 'function') {
      onChange(newMode);
    }
  });

  return container;
}

/**
 * Returns the HTML string for a measurement toggle (for use in template literals).
 * @param {string} currentMode - Current mode ('metric' or 'imperial')
 * @param {string} toggleId - Unique ID for the toggle container
 * @returns {string} HTML string
 */
export function getMeasurementToggleHTML(currentMode, toggleId = 'measurement-toggle') {
  const metricActive = currentMode === 'metric' ? ' is-active vareoncalc-measurement-toggle__btn--active' : '';
  const imperialActive = currentMode === 'imperial' ? ' is-active vareoncalc-measurement-toggle__btn--active' : '';
  const metricLabel = __('Metric', 'vareon-calculator-suite-lite');
  const imperialLabel = __('Imperial', 'vareon-calculator-suite-lite');
  const ariaLabel = __('Measurement system', 'vareon-calculator-suite-lite');

  return `
    <div class="vareoncalc-toggle vareoncalc-measurement-toggle" id="${toggleId}" data-active="${currentMode}" data-mode="${currentMode}" role="group" aria-label="${ariaLabel}">
      <div class="vareoncalc-toggle__track">
        <button type="button" class="vareoncalc-toggle__option vareoncalc-measurement-toggle__btn vareoncalc-measurement-toggle__btn--metric${metricActive}" data-mode="metric" aria-pressed="${currentMode === 'metric'}">${metricLabel}</button>
        <button type="button" class="vareoncalc-toggle__option vareoncalc-measurement-toggle__btn vareoncalc-measurement-toggle__btn--imperial${imperialActive}" data-mode="imperial" aria-pressed="${currentMode === 'imperial'}">${imperialLabel}</button>
      </div>
    </div>
  `;
}

/**
 * Attaches event listener to a measurement toggle rendered via getMeasurementToggleHTML.
 * @param {HTMLElement} container - The parent container where the toggle was rendered
 * @param {string} toggleId - The ID used when creating the toggle
 * @param {Function} onChange - Callback when mode changes
 */
export function attachMeasurementToggleListener(container, toggleId, onChange) {
  const toggle = container.querySelector(`#${toggleId}`);
  if (!toggle) return;

  toggle.addEventListener('click', (e) => {
    const btn = e.target.closest('.vareoncalc-measurement-toggle__btn');
    if (!btn) return;

    const newMode = btn.dataset.mode;
    const buttons = toggle.querySelectorAll('.vareoncalc-measurement-toggle__btn');

    // Check if already active
    if (btn.classList.contains('is-active') || btn.classList.contains('vareoncalc-measurement-toggle__btn--active')) return;

    // Update active states
    buttons.forEach(b => {
      const isActive = b.dataset.mode === newMode;
      b.classList.toggle('is-active', isActive);
      b.classList.toggle('vareoncalc-measurement-toggle__btn--active', isActive);
      b.setAttribute('aria-pressed', isActive ? 'true' : 'false');
    });
    toggle.dataset.active = newMode;
    toggle.dataset.mode = newMode;

    // Save preference to localStorage (only effective when system is 'mixed')
    saveMeasurementPreference(newMode);

    if (typeof onChange === 'function') {
      onChange(newMode);
    }
  });
}

/**
 * Disables the option from the select element when the measurement system forbids it.
 */
export function enforceMeasurementLock(selectEl, modeToDisable) {
  if (!selectEl || !modeToDisable) return;
  const option = selectEl.querySelector(`option[value="${modeToDisable}"]`);
  if (option) {
    option.disabled = true;
    option.hidden = true;
  }
}

export function convertDistance(value, fromUnit, toUnit) {
  if (!isFinite(value)) return 0;
  if (fromUnit === toUnit) return value;

  if (fromUnit === 'miles' && toUnit === 'km') return value * MILE_TO_KM;
  if (fromUnit === 'km' && toUnit === 'miles') return value / MILE_TO_KM;
  return value;
}

export function convertWeight(value, fromUnit, toUnit) {
  if (!isFinite(value)) return 0;
  if (fromUnit === toUnit) return value;

  if (fromUnit === 'lbs' && toUnit === 'kg') return value * LB_TO_KG;
  if (fromUnit === 'kg' && toUnit === 'lbs') return value / LB_TO_KG;
  return value;
}

export function convertLength(value, fromUnit, toUnit) {
  if (!isFinite(value)) return 0;
  if (fromUnit === toUnit) return value;

  if (fromUnit === 'feet' && toUnit === 'meters') return value * FOOT_TO_METER;
  if (fromUnit === 'meters' && toUnit === 'feet') return value / FOOT_TO_METER;
  if (fromUnit === 'inches' && toUnit === 'cm') return value * INCH_TO_CM;
  if (fromUnit === 'cm' && toUnit === 'inches') return value / INCH_TO_CM;
  return value;
}

export function convertArea(value, fromUnit, toUnit) {
  if (!isFinite(value)) return 0;
  if (fromUnit === toUnit) return value;

  if (fromUnit === 'sqft' && toUnit === 'sqm') return value * SQFT_TO_SQM;
  if (fromUnit === 'sqm' && toUnit === 'sqft') return value / SQFT_TO_SQM;
  return value;
}

export function convertVolume(value, fromUnit, toUnit) {
  if (!isFinite(value)) return 0;
  if (fromUnit === toUnit) return value;

  if (fromUnit === 'gallons' && toUnit === 'liters') return value * GALLON_TO_LITER;
  if (fromUnit === 'liters' && toUnit === 'gallons') return value / GALLON_TO_LITER;
  return value;
}

export function convertSpeed(value, fromUnit, toUnit) {
  if (!isFinite(value)) return 0;
  if (fromUnit === toUnit) return value;

  if (fromUnit === 'mph' && toUnit === 'kmh') return value * MILE_TO_KM;
  if (fromUnit === 'kmh' && toUnit === 'mph') return value / MILE_TO_KM;
  return value;
}

export function convertFuelEfficiency(value, fromUnit, toUnit) {
  if (!isFinite(value) || value === 0) return 0;
  if (fromUnit === toUnit) return value;

  // mpg <-> L/100km conversions
  if (fromUnit === 'mpg' && toUnit === 'l_per_100km') {
    return 235.214583 / value;
  }
  if (fromUnit === 'l_per_100km' && toUnit === 'mpg') {
    return 235.214583 / value;
  }
  if (fromUnit === 'mpg' && toUnit === 'km_per_liter') {
    return value * MILE_TO_KM / 3.78541;
  }
  if (fromUnit === 'km_per_liter' && toUnit === 'mpg') {
    return value * 3.78541 / MILE_TO_KM;
  }
  return value;
}

export function convertEnergyPerDistance(value, fromUnit, toUnit) {
  if (!isFinite(value) || value === 0) return 0;
  if (fromUnit === toUnit) return value;

  // kWh/100mi <-> kWh/100km
  if (fromUnit === 'kwh_per_100mi' && toUnit === 'kwh_per_100km') {
    return value / MILE_TO_KM;
  }
  if (fromUnit === 'kwh_per_100km' && toUnit === 'kwh_per_100mi') {
    return value * MILE_TO_KM;
  }
  return value;
}

// -------------------------------------------------------------
// Feet + Inches Height Helpers
// -------------------------------------------------------------

/**
 * Converts centimeters to feet and inches.
 * @param {number} cm - Height in centimeters
 * @returns {{ feet: number, inches: number }} Object with feet (int) and inches (decimal)
 */
export function cmToFeetInches(cm) {
  if (!isFinite(cm) || cm <= 0) return { feet: 0, inches: 0 };
  const totalInches = cm / INCH_TO_CM;
  const feet = Math.floor(totalInches / 12);
  const inches = totalInches % 12;
  return { feet, inches: parseFloat(inches.toFixed(1)) };
}

/**
 * Converts feet and inches to centimeters.
 * @param {number} feet - Feet portion (integer)
 * @param {number} inches - Inches portion (can be decimal, should be < 12)
 * @returns {number} Height in centimeters
 */
export function feetInchesToCm(feet, inches) {
  const ft = parseFloat(feet) || 0;
  const inc = parseFloat(inches) || 0;
  const totalInches = (ft * 12) + inc;
  return totalInches * INCH_TO_CM;
}

/**
 * Converts feet and inches to total inches.
 * @param {number} feet - Feet portion
 * @param {number} inches - Inches portion
 * @returns {number} Total inches
 */
export function feetInchesToTotalInches(feet, inches) {
  const ft = parseFloat(feet) || 0;
  const inc = parseFloat(inches) || 0;
  return (ft * 12) + inc;
}

/**
 * Converts total inches to feet and inches.
 * @param {number} totalInches - Total inches
 * @returns {{ feet: number, inches: number }} Object with feet (int) and inches (decimal)
 */
export function totalInchesToFeetInches(totalInches) {
  if (!isFinite(totalInches) || totalInches <= 0) return { feet: 0, inches: 0 };
  const feet = Math.floor(totalInches / 12);
  const inches = totalInches % 12;
  return { feet, inches: parseFloat(inches.toFixed(1)) };
}

/**
 * Normalizes feet and inches so inches is always < 12.
 * Rolls over excess inches into feet (e.g., 5ft 14in -> 6ft 2in).
 * @param {number} feet - Feet portion
 * @param {number} inches - Inches portion (can be >= 12)
 * @returns {{ feet: number, inches: number }} Normalized values with inches < 12
 */
export function normalizeFeetInches(feet, inches) {
  const ft = parseFloat(feet) || 0;
  const inc = parseFloat(inches) || 0;
  if (inc < 12 && inc >= 0) {
    return { feet: ft, inches: parseFloat(inc.toFixed(1)) };
  }
  const totalInches = (ft * 12) + inc;
  if (totalInches <= 0) return { feet: 0, inches: 0 };
  const newFeet = Math.floor(totalInches / 12);
  const newInches = totalInches % 12;
  return { feet: newFeet, inches: parseFloat(newInches.toFixed(1)) };
}

