/* I18n provider, hooks, and routing helpers.
 * Loaded via <script type="text/babel"> AFTER Router.jsx and locale files,
 * BEFORE App.jsx. Exposes window.{I18nProvider, useI18n, useT, usePrefs,
 * localizePath, translatePlace, LANGS, getLogicalPath, formatDistanceKm,
 * formatTemperatureC}. */

const LANGS = ['en', 'es', 'ca'];
const DEFAULT_LANG = 'en';
const STORAGE_KEY = 'neu.lang';
const DISTANCE_UNITS = ['metric', 'imperial'];
const TEMPERATURE_UNITS = ['c', 'f'];
const DISTANCE_STORAGE_KEY = 'neu.distanceUnit';
const TEMPERATURE_STORAGE_KEY = 'neu.temperatureUnit';

/* ── localStorage helpers (Safari private mode safe) ───────────── */
function readStoredLang() {
  try {
    const v = window.localStorage.getItem(STORAGE_KEY);
    return LANGS.includes(v) ? v : null;
  } catch { return null; }
}
function writeStoredLang(lang) {
  try { window.localStorage.setItem(STORAGE_KEY, lang); } catch { /* ignore */ }
}
function readStoredPref(key, validValues) {
  try {
    const v = window.localStorage.getItem(key);
    return validValues.includes(v) ? v : null;
  } catch { return null; }
}
function writeStoredPref(key, value) {
  try { window.localStorage.setItem(key, value); } catch { /* ignore */ }
}

/* ── Browser language detection ─────────────────────────────────── */
function detectBrowserLang() {
  const tag = (navigator.language || navigator.userLanguage || '').toLowerCase();
  if (tag.startsWith('es')) return 'es';
  if (tag.startsWith('ca')) return 'ca';
  return DEFAULT_LANG;
}
function browserLocaleTag() {
  return (navigator.language || navigator.userLanguage || '').toLowerCase();
}
function usesImperialByDefault() {
  return browserLocaleTag().startsWith('en-us');
}
function detectDistanceUnit() {
  return usesImperialByDefault() ? 'imperial' : 'metric';
}
function detectTemperatureUnit() {
  return usesImperialByDefault() ? 'f' : 'c';
}

/* ── Unit formatting ────────────────────────────────────────────── */
function distanceLabel(unit) {
  return unit === 'imperial' ? 'Mi' : 'Km';
}
function temperatureLabel(unit) {
  return unit === 'f' ? 'F' : 'C';
}
function kmToDisplay(km, unit) {
  const n = Number(km);
  if (!isFinite(n)) return 0;
  return unit === 'imperial' ? n * 0.621371 : n;
}
function cToDisplay(celsius, unit) {
  const n = Number(celsius);
  if (!isFinite(n)) return 0;
  return unit === 'f' ? (n * 9 / 5) + 32 : n;
}
function formatMeasure(value, unitLabel, decimals = 1) {
  const n = Number(value);
  if (!isFinite(n)) return `0 ${unitLabel}`;
  const precision = Math.abs(n) >= 100 || Number.isInteger(n) ? 0 : decimals;
  return `${n.toFixed(precision)} ${unitLabel}`;
}
function formatDistanceKm(km, unit = 'metric') {
  return formatMeasure(kmToDisplay(km, unit), distanceLabel(unit), 1);
}
function formatTemperatureC(celsius, unit = 'c') {
  return `${Math.round(cToDisplay(celsius, unit))}°${temperatureLabel(unit)}`;
}

/* ── Path helpers ───────────────────────────────────────────────── */
/* localizePath('en', '/resorts/foo')  → '/resorts/foo'   (no prefix for default)
 * localizePath('es', '/resorts/foo')  → '/es/resorts/foo'
 * localizePath('ca', '/')             → '/ca'                              */
function localizePath(lang, logicalPath) {
  const path = logicalPath || '/';
  if (lang === DEFAULT_LANG || !LANGS.includes(lang)) {
    return path === '' ? '/' : path;
  }
  if (path === '/' || path === '') return `/${lang}`;
  return `/${lang}${path}`;
}

/* getLogicalPath: strip lang prefix from a real pathname, returning '/...' */
function getLogicalPath(pathname) {
  const parts = (pathname || '/').split('/').filter(Boolean);
  if (parts[0] && LANGS.includes(parts[0])) parts.shift();
  return '/' + parts.join('/');
}

/* ── Place name translation ─────────────────────────────────────── */
function translatePlace(name, lang) {
  if (!name) return name;
  if (lang === DEFAULT_LANG) return name;
  const entry = window.NEU_I18N_PLACES?.[name];
  if (!entry) return name;
  return entry[lang] || name;
}

/* ── Dot-path lookup with interpolation + EN fallback ───────────── */
function lookupKey(table, dotPath) {
  if (!table) return undefined;
  const parts = dotPath.split('.');
  let cur = table;
  for (const p of parts) {
    if (cur == null || typeof cur !== 'object') return undefined;
    cur = cur[p];
  }
  return cur;
}
function interpolate(template, vars) {
  if (typeof template !== 'string' || !vars) return template;
  return template.replace(/\{(\w+)\}/g, (_, k) => (vars[k] != null ? String(vars[k]) : `{${k}}`));
}

/* ── Provider + hooks ───────────────────────────────────────────── */
const I18nContext = React.createContext(null);
const PrefsContext = React.createContext(null);

function I18nProvider({ children }) {
  // Guard: locale tables must be loaded before render.
  if (!window.NEU_I18N || !window.NEU_I18N.en) {
    console.error('[i18n] window.NEU_I18N.en missing — locale scripts loaded out of order?');
    return null;
  }

  const route = useRoute();
  const [lang, setLangState] = React.useState(() => {
    // Initial: URL prefix → stored → browser → default.
    if (route.lang) return route.lang;
    return readStoredLang() || detectBrowserLang();
  });

  // Sync when URL prefix changes (e.g. via popstate or LangSelector navigate)
  React.useEffect(() => {
    if (route.lang && route.lang !== lang) setLangState(route.lang);
    // First-visit auto-redirect: URL has no prefix and resolved lang ≠ default.
    if (!route.lang && lang !== DEFAULT_LANG) {
      const current = window.location.pathname;
      const target = localizePath(lang, getLogicalPath(current));
      if (target !== current) window.replaceRoute(target);
    }
  }, [route.lang, lang]);

  // Persist on every change.
  React.useEffect(() => { writeStoredLang(lang); }, [lang]);

  // <html lang> + canonical/hreflang. document.title is owned by AppInner so it
  // can include the active resort name; we only handle <html lang> + head links here.
  React.useEffect(() => {
    document.documentElement.lang = lang;
    updateHeadLinks(lang, getLogicalPath(window.location.pathname));
  }, [lang, route.view, route.id]);

  // setLang: navigate so the URL becomes the source of truth.
  const setLang = React.useCallback((nextLang) => {
    if (!LANGS.includes(nextLang) || nextLang === lang) return;
    const logical = getLogicalPath(window.location.pathname);
    const target = localizePath(nextLang, logical);
    setLangState(nextLang);
    window.navigate(target);
  }, [lang]);

  const t = React.useMemo(() => {
    const en = window.NEU_I18N.en;
    const cur = window.NEU_I18N[lang] || en;
    return (path, vars) => {
      const val = lookupKey(cur, path);
      if (val !== undefined) return interpolate(val, vars);
      const fallback = lookupKey(en, path);
      if (fallback !== undefined) return interpolate(fallback, vars);
      console.warn(`[i18n] missing key: ${path}`);
      return path;
    };
  }, [lang]);

  const value = React.useMemo(() => ({ lang, setLang, t }), [lang, setLang, t]);
  return React.createElement(I18nContext.Provider, { value }, children);
}

function useI18n() {
  const ctx = React.useContext(I18nContext);
  if (!ctx) throw new Error('useI18n must be used within <I18nProvider>');
  return ctx;
}
function useT() { return useI18n().t; }

function PreferencesProvider({ children }) {
  const [distanceUnit, setDistanceUnitState] = React.useState(() => (
    readStoredPref(DISTANCE_STORAGE_KEY, DISTANCE_UNITS) || detectDistanceUnit()
  ));
  const [temperatureUnit, setTemperatureUnitState] = React.useState(() => (
    readStoredPref(TEMPERATURE_STORAGE_KEY, TEMPERATURE_UNITS) || detectTemperatureUnit()
  ));

  React.useEffect(() => { writeStoredPref(DISTANCE_STORAGE_KEY, distanceUnit); }, [distanceUnit]);
  React.useEffect(() => { writeStoredPref(TEMPERATURE_STORAGE_KEY, temperatureUnit); }, [temperatureUnit]);

  const setDistanceUnit = React.useCallback((next) => {
    if (DISTANCE_UNITS.includes(next)) setDistanceUnitState(next);
  }, []);
  const setTemperatureUnit = React.useCallback((next) => {
    if (TEMPERATURE_UNITS.includes(next)) setTemperatureUnitState(next);
  }, []);

  const value = React.useMemo(() => ({
    distanceUnit,
    temperatureUnit,
    setDistanceUnit,
    setTemperatureUnit,
  }), [distanceUnit, temperatureUnit, setDistanceUnit, setTemperatureUnit]);

  return React.createElement(PrefsContext.Provider, { value }, children);
}

function usePrefs() {
  const ctx = React.useContext(PrefsContext);
  if (!ctx) throw new Error('usePrefs must be used within <PreferencesProvider>');
  return ctx;
}

/* ── SEO head links (canonical + hreflang + x-default) ──────────── */
function updateHeadLinks(currentLang, logicalPath) {
  const origin = window.location.origin;
  // Canonical: current lang's URL.
  const canonical = origin + localizePath(currentLang, logicalPath);
  setHeadLink('canonical', null, canonical);
  // Alternates for every supported lang + x-default → EN URL.
  for (const l of LANGS) setHeadLink('alternate', l, origin + localizePath(l, logicalPath));
  setHeadLink('alternate', 'x-default', origin + localizePath(DEFAULT_LANG, logicalPath));
}
function setHeadLink(rel, hreflang, href) {
  const sel = hreflang
    ? `link[rel="${rel}"][hreflang="${hreflang}"][data-i18n]`
    : `link[rel="${rel}"][data-i18n]:not([hreflang])`;
  let el = document.head.querySelector(sel);
  if (!el) {
    el = document.createElement('link');
    el.setAttribute('rel', rel);
    if (hreflang) el.setAttribute('hreflang', hreflang);
    el.setAttribute('data-i18n', '');
    document.head.appendChild(el);
  }
  el.setAttribute('href', href);
}

Object.assign(window, {
  I18nProvider, PreferencesProvider, useI18n, useT, usePrefs,
  localizePath, getLogicalPath, translatePlace,
  formatDistanceKm, formatTemperatureC, kmToDisplay, cToDisplay,
  distanceLabel, temperatureLabel,
  LANGS, DISTANCE_UNITS, TEMPERATURE_UNITS,
});
