/**
 * Water Log — internationalization (i18n).
 *
 * Single source of truth for the user-facing strings in the mobile
 * (`/water`) and admin (`/water/admin`) portals. Both portals share
 * the same `wl_lang` cookie and the same audience (Tuxedo field
 * workers + ditch supervisors, mostly Spanish-first).
 *
 * **Why this lives in `lib/` rather than each component:**
 *
 *   - The two portals used to have divergent i18n implementations:
 *     `WaterAdminClient.tsx` had a full `LABELS` dict; the mobile
 *     screens had no i18n at all. Lifting the labels here lets the
 *     admin client drop its copy and lets the mobile app adopt
 *     Spanish without re-inventing the dictionary.
 *   - A single source means when we add a string to one screen we
 *     notice the other and add it there too (or at least see that
 *     it's missing).
 *   - The labels are pure data — no React, no `next/headers`, no
 *     `cookies()` — so they're safe to import from client
 *     components, server components, and unit tests alike.
 *
 * Persistence: the `wl_lang` cookie. See `./session-server.ts`
 * (currently `setWaterLang` in `actions/water-log/field.ts` sets it
 * via a thin wrapper; we keep that wrapper for back-compat).
 *
 * Default: Spanish — the deployed audience is predominantly
 * Spanish-speaking. Override with the cookie or with
 * `detectInitialLang()`.
 */

export const WL_LANG_COOKIE = "wl_lang";

export type Lang = "en" | "es";

/**
 * The full label dictionary. Organized by screen so the writer can
 * find the right string quickly and so we can see at a glance which
 * screens are missing translations.
 */
export type Labels = {
  /** Strings shared by multiple screens. */
  common: {
    cancel: string;
    save: string;
    saving: string;
    back: string;
    signOut: string;
    a11yBackToHeadgates: string;
    a11yChangeHeadgate: string;
    a11ySignOut: string;
    /** ARIA group label for the language toggle. */
    a11yLanguage: string;
  };
  /** The brand strip shown on the PIN and Success screens. */
  brand: {
    waterLog: string;
  };
  /** `/water` PIN entry screen. */
  pin: {
    title: string;
    caption: string;
    verifying: string;
    unlock: string;
    forgot: string;
    genericError: string;
    a11yPin: string;
    a11yPinEntry: string;
  };
  /** `/water` headgate list screen. */
  headgates: {
    title: string;
    signedInAs: (name: string) => string;
    activeSection: string;
    emptyTitle: string;
    emptyBody: string;
    pullToRefresh: string;
    thresholdHigh: string;
    thresholdLow: string;
    refresh: string;
    refreshing: string;
    loadError: string;
  };
  /** `/water` measurement entry screen. */
  log: {
    title: string;
    measurement: string;
    unit: string;
    timestamp: string;
    loggedNow: string;
    notes: string;
    notesOptional: string;
    notesPlaceholder: string;
    notesVisibility: string;
    measurementError: string;
    implausiblyLarge: string;
    submit: string;
    submitting: string;
    /** Shown when a session expires mid-shift; bounce user to PIN. */
    sessionExpired: string;
    /** Generic submit-failure fallback (e.g. server-side validation). */
    submitError: string;
    /** Defensive guard — shouldn't ever happen. */
    noHeadgateSelected: string;
    normalRange: (low: number, high: number, unit: string) => string;
    alertAbove: (high: number, unit: string) => string;
    alertBelow: (low: number, unit: string) => string;
  };
  /** `/water` success screen after submit. */
  success: {
    title: string;
    logAnother: string;
    backToHeadgates: string;
    thanks: string;
    loggedBy: (name: string) => string;
  };
  /** Headgate status string shown in card subtitles. */
  status: {
    open: string;
    openReady: string;
    closed: string;
    maintenance: string;
  };
  /** Unit labels. The keys are the canonical English codes stored in
   *  the DB. Values are the display strings per language. */
  units: {
    CFS: string;
    GPM: string;
    gal: string;
    "ac-in": string;
    "ac-ft": string;
    holes: string;
  };
  /** Short relative-time phrases for the headgate card meta row. */
  format: {
    neverLogged: string;
    justNow: string;
    minutesAgo: (n: number) => string;
    hoursAgo: (n: number) => string;
  };
};

export const LABELS: Record<Lang, Labels> = {
  en: {
    common: {
      cancel: "Cancel",
      save: "Save",
      saving: "Saving…",
      back: "Back",
      signOut: "Sign out",
      a11yBackToHeadgates: "Back to headgates",
      a11yChangeHeadgate: "Change headgate",
      a11ySignOut: "Sign out",
      a11yLanguage: "Language",
    },
    brand: {
      waterLog: "TUXEDO WATER LOG",
    },
    pin: {
      title: "Enter your PIN",
      caption: "Sign in to log a water reading",
      verifying: "Verifying…",
      unlock: "Unlock",
      forgot: "Forgot your PIN? Ask the ditch supervisor.",
      genericError: "Something went wrong. Try again.",
      a11yPin: "PIN",
      a11yPinEntry: "PIN entry — tap to focus",
    },
    headgates: {
      title: "Headgates",
      signedInAs: (name) => `Signed in as ${name}`,
      activeSection: "Active headgates",
      emptyTitle: "No active headgates",
      emptyBody:
        "Once your supervisor activates a headgate, it'll show up here. Pull down to check for updates.",
      pullToRefresh: "Pull down to refresh the list",
      thresholdHigh: "Hi",
      thresholdLow: "Lo",
      refresh: "Refresh",
      refreshing: "Checking…",
      loadError: "Couldn't load headgates. Pull down to try again.",
    },
    log: {
      title: "Log Reading",
      measurement: "Measurement",
      unit: "Unit",
      timestamp: "Timestamp",
      loggedNow: "Logged now",
      notes: "Notes",
      notesOptional: "optional",
      notesPlaceholder:
        "Anything the supervisor should know about this reading?",
      notesVisibility: "Visible to admins only",
      measurementError:
        "Enter a measurement greater than or equal to 0",
      implausiblyLarge: "That value is implausibly large",
      submit: "Submit Log",
      submitting: "Submitting…",
      sessionExpired: "Your session expired. Please sign in again.",
      submitError: "Something went wrong submitting that entry. Try again.",
      noHeadgateSelected: "Pick a headgate first.",
      normalRange: (low, high, unit) =>
        `Normal range: ${low} – ${high} ${unit}`,
      alertAbove: (high, unit) => `Alert above ${high} ${unit}`,
      alertBelow: (low, unit) => `Alert below ${low} ${unit}`,
    },
    success: {
      title: "Reading logged",
      logAnother: "Log Another Entry",
      backToHeadgates: "Back to Headgates",
      thanks: "Thanks for keeping the records flowing.",
      loggedBy: (name) => `Logged by ${name}`,
    },
    status: {
      open: "Open",
      openReady: "Open · Ready to log",
      closed: "Closed",
      maintenance: "Under maintenance",
    },
    units: {
      CFS: "CFS",
      GPM: "GPM",
      gal: "gal",
      "ac-in": "ac-in",
      "ac-ft": "ac-ft",
      holes: "holes",
    },
    format: {
      neverLogged: "Never logged",
      justNow: "Just now",
      minutesAgo: (n) => `${n}m ago`,
      hoursAgo: (n) => `${n}h ago`,
    },
  },
  es: {
    common: {
      cancel: "Cancelar",
      save: "Guardar",
      saving: "Guardando…",
      back: "Atrás",
      signOut: "Salir",
      a11yBackToHeadgates: "Volver a compuertas",
      a11yChangeHeadgate: "Cambiar compuerta",
      a11ySignOut: "Cerrar sesión",
      a11yLanguage: "Idioma",
    },
    brand: {
      waterLog: "REGISTRO DE AGUA TUXEDO",
    },
    pin: {
      title: "Ingresa tu PIN",
      caption: "Inicia sesión para registrar una lectura de agua",
      verifying: "Verificando…",
      unlock: "Desbloquear",
      forgot: "¿Olvidaste tu PIN? Pregúntale al supervisor.",
      genericError: "Algo salió mal. Inténtalo de nuevo.",
      a11yPin: "PIN",
      a11yPinEntry: "Entrada de PIN — toca para enfocar",
    },
    headgates: {
      title: "Compuertas",
      signedInAs: (name) => `Sesión iniciada como ${name}`,
      activeSection: "Compuertas activas",
      emptyTitle: "No hay compuertas activas",
      emptyBody:
        "Cuando tu supervisor active una compuerta, aparecerá aquí. Jala hacia abajo para actualizar.",
      pullToRefresh: "Jala hacia abajo para actualizar la lista",
      thresholdHigh: "Alto",
      thresholdLow: "Bajo",
      refresh: "Actualizar",
      refreshing: "Verificando…",
      loadError: "No se pudieron cargar las compuertas. Jala para intentar de nuevo.",
    },
    log: {
      title: "Registrar lectura",
      measurement: "Medición",
      unit: "Unidad",
      timestamp: "Hora",
      loggedNow: "Registrando ahora",
      notes: "Notas",
      notesOptional: "opcional",
      notesPlaceholder:
        "¿Algo que el supervisor deba saber sobre esta lectura?",
      notesVisibility: "Visible solo para administradores",
      measurementError:
        "Ingresa una medición mayor o igual a 0",
      implausiblyLarge: "Ese valor es demasiado grande",
      submit: "Enviar registro",
      submitting: "Enviando…",
      sessionExpired: "Tu sesión expiró. Inicia sesión otra vez.",
      submitError:
        "Algo salió mal al enviar ese registro. Inténtalo de nuevo.",
      noHeadgateSelected: "Elige una compuerta primero.",
      normalRange: (low, high, unit) =>
        `Rango normal: ${low} – ${high} ${unit}`,
      alertAbove: (high, unit) => `Alerta arriba de ${high} ${unit}`,
      alertBelow: (low, unit) => `Alerta abajo de ${low} ${unit}`,
    },
    success: {
      title: "Lectura registrada",
      logAnother: "Registrar otra",
      backToHeadgates: "Volver a compuertas",
      thanks: "Gracias por mantener los registros al día.",
      loggedBy: (name) => `Registrado por ${name}`,
    },
    status: {
      open: "Abierta",
      openReady: "Abierta · Lista para registrar",
      closed: "Cerrada",
      maintenance: "En mantenimiento",
    },
    units: {
      CFS: "CFS",
      GPM: "GPM",
      gal: "gal",
      "ac-in": "ac-in",
      "ac-ft": "ac-ft",
      holes: "hoyos",
    },
    format: {
      neverLogged: "Nunca registrada",
      justNow: "Ahora",
      minutesAgo: (n) => `hace ${n}m`,
      hoursAgo: (n) => `hace ${n}h`,
    },
  },
};

/**
 * Detect the initial language for a freshly-hydrated client.
 *
 * Order of preference:
 *   1. The `wl_lang` cookie (the user's last explicit choice).
 *   2. `navigator.language` (with weak "starts with" matching).
 *   3. Spanish (the deployed audience is predominantly Spanish-speaking).
 *
 * Safe to call during SSR — when `document` is undefined, returns the
 * default (`es`). The component calling this should pair the read
 * with a `useEffect` to re-detect on the client if needed.
 */
export function detectInitialLang(): Lang {
  if (typeof document === "undefined") return "es";
  const cookie = document.cookie.match(/wl_lang=(en|es)/)?.[1];
  if (cookie === "en" || cookie === "es") return cookie;
  if (typeof navigator !== "undefined") {
    const lang = navigator.language?.toLowerCase() ?? "";
    if (lang.startsWith("en")) return "en";
  }
  return "es";
}

/** Persist the user's language choice. Client-side only. */
export function setLangCookie(lang: Lang): void {
  if (typeof document === "undefined") return;
  // 1 year max-age — long enough that returning users see their
  // preferred language without re-prompting.
  document.cookie = `${WL_LANG_COOKIE}=${lang}; path=/; max-age=31536000; SameSite=Lax`;
}

/** Get the labels dictionary for a given lang. */
export function getT(lang: Lang): Labels {
  return LABELS[lang];
}

/**
 * Display string for a headgate's stored `unit` value, localized.
 * Falls back to the raw unit string when not in the catalog (so we
 * don't break on legacy or admin-typed custom units).
 */
export function displayUnit(unit: string, lang: Lang): string {
  const t = LABELS[lang].units;
  if (unit === "CFS") return t.CFS;
  if (unit === "GPM") return t.GPM;
  if (unit === "gal") return t.gal;
  if (unit === "ac-in") return t["ac-in"];
  if (unit === "ac-ft") return t["ac-ft"];
  if (unit === "holes") return t.holes;
  return unit;
}