/**
 * Measurement unit formatting — Metric / Imperial.
 *
 * The active system is persisted in localStorage('measurement-system').
 * Every formatter reads the current setting so the UI updates immediately
 * after the user flips the toggle.
 *
 * All input values are in metres (length) or square metres (area).
 */

// ── Conversion constants ────────────────────────────────────────────────────
const M_TO_FT   = 3.28084;
const M_TO_MI   = 0.000621371;
const SQM_TO_SQFT = 10.7639;
const SQM_TO_ACRE = 0.000247105;
const SQM_TO_SQMI = 3.861e-7;

// ── System accessor ─────────────────────────────────────────────────────────

/** @returns {'metric'|'imperial'} */
export function getSystem() {
  return localStorage.getItem('measurement-system') || 'metric';
}

// ── Length / distance ───────────────────────────────────────────────────────

/**
 * Format a length value (in metres) for display.
 * Metric:   m / km
 * Imperial: ft / mi
 */
export function formatLength(metres) {
  if (getSystem() === 'imperial') {
    const ft = metres * M_TO_FT;
    if (ft >= 5280) {
      return (Math.round(metres * M_TO_MI * 100) / 100) + ' mi';
    }
    return Math.round(ft) + ' ft';
  }
  // metric
  if (metres > 1000) {
    return (Math.round(metres / 1000 * 100) / 100) + ' km';
  }
  return (Math.round(metres * 100) / 100) + ' m';
}

/**
 * Format a length with both large and small units (for info popups).
 * Metric:   "1.23 km  (1,230 m)"   or   "456 m"
 * Imperial: "1.23 mi  (6,494 ft)"   or   "456 ft"
 */
export function formatLengthFull(metres) {
  if (getSystem() === 'imperial') {
    const ft = metres * M_TO_FT;
    const mi = metres * M_TO_MI;
    if (ft >= 5280) {
      return `${mi.toFixed(2)} mi  (${ft.toLocaleString('en', { maximumFractionDigits: 0 })} ft)`;
    }
    return `${ft.toLocaleString('en', { maximumFractionDigits: 1 })} ft`;
  }
  if (metres >= 1000) {
    return `${(metres / 1000).toFixed(2)} km  (${metres.toLocaleString('en', { maximumFractionDigits: 0 })} m)`;
  }
  return `${metres.toLocaleString('en', { maximumFractionDigits: 1 })} m`;
}

// ── Area ────────────────────────────────────────────────────────────────────

/**
 * Format an area value (in square metres) for display.
 * Metric:   m² / km²
 * Imperial: ft² / acres / mi²
 */
export function formatArea(sqMetres) {
  if (getSystem() === 'imperial') {
    const acres = sqMetres * SQM_TO_ACRE;
    if (acres >= 640) {
      return (Math.round(sqMetres * SQM_TO_SQMI * 100) / 100) + ' mi²';
    }
    if (acres >= 1) {
      return (Math.round(acres * 100) / 100) + ' acres';
    }
    return Math.round(sqMetres * SQM_TO_SQFT).toLocaleString('en') + ' ft²';
  }
  // metric
  if (sqMetres > 1000000) {
    return (Math.round(sqMetres / 1000000 * 100) / 100) + ' km²';
  }
  return (Math.round(sqMetres * 100) / 100) + ' m²';
}

/**
 * Format an area with both large and small units (for info popups).
 * Metric:   "1.23 km²  (1,230,000 m²)"   or   "456 m²"
 * Imperial: "1.23 mi²  (787 acres)"   or   "2.5 acres"   or   "456 ft²"
 */
export function formatAreaFull(sqMetres) {
  if (getSystem() === 'imperial') {
    const sqft = sqMetres * SQM_TO_SQFT;
    const acres = sqMetres * SQM_TO_ACRE;
    const sqmi = sqMetres * SQM_TO_SQMI;
    if (acres >= 640) {
      return `${sqmi.toFixed(2)} mi²  (${acres.toLocaleString('en', { maximumFractionDigits: 0 })} acres)`;
    }
    if (acres >= 1) {
      return `${acres.toLocaleString('en', { maximumFractionDigits: 1 })} acres  (${sqft.toLocaleString('en', { maximumFractionDigits: 0 })} ft²)`;
    }
    return `${sqft.toLocaleString('en', { maximumFractionDigits: 0 })} ft²`;
  }
  if (sqMetres > 1000000) {
    return `${(sqMetres / 1000000).toFixed(2)} km²  (${sqMetres.toLocaleString('en', { maximumFractionDigits: 0 })} m²)`;
  }
  return `${sqMetres.toLocaleString('en', { maximumFractionDigits: 0 })} m²`;
}

// ── Circle helper ───────────────────────────────────────────────────────────

/**
 * Format the area of a circle given its radius (in metres).
 */
export function formatCircleExtent(radiusMetres) {
  return formatArea(Math.PI * radiusMetres * radiusMetres);
}
