/**
 * Enhetsvisning och -tolkning i appen (i18n-spec §9, §11).
 * Canonical koder (GRAM, TABLESPOON …) kommer från API:t; här översätts de till
 * lokala förkortningar och tolkas tillbaka från användarens fritext.
 * Måttsystem-konvertering (M5) sker via displayQuantity i shared-types.
 * DB-tabellen unit_translations är källan för fler språk (API: /v1/i18n/units).
 */
import { displayQuantity, type MeasurementSystem, type Unit } from "@app/shared-types";

const LABELS: Record<string, Record<string, string>> = {
  sv: {
    GRAM: "g",
    KILOGRAM: "kg",
    MILLILITER: "ml",
    DECILITER: "dl",
    LITER: "l",
    TEASPOON: "tsk",
    TABLESPOON: "msk",
    CUP_US: "cup",
    FLUID_OUNCE_US: "fl oz",
    OUNCE: "oz",
    POUND: "lb",
    COUNT: "st",
    PORTION: "portion",
    PINCH: "krm",
    SLICE: "skiva",
    CLOVE: "klyfta",
    CAN: "burk",
    PACKAGE: "paket",
  },
  en: {
    GRAM: "g",
    KILOGRAM: "kg",
    MILLILITER: "ml",
    DECILITER: "dl",
    LITER: "l",
    TEASPOON: "tsp",
    TABLESPOON: "tbsp",
    CUP_US: "cup",
    FLUID_OUNCE_US: "fl oz",
    OUNCE: "oz",
    POUND: "lb",
    COUNT: "pcs",
    PORTION: "serving",
    PINCH: "pinch",
    SLICE: "slice",
    CLOVE: "clove",
    CAN: "can",
    PACKAGE: "pack",
  },
  es: {
    GRAM: "g",
    KILOGRAM: "kg",
    MILLILITER: "ml",
    DECILITER: "dl",
    LITER: "l",
    TEASPOON: "cdta",
    TABLESPOON: "cda",
    CUP_US: "taza",
    FLUID_OUNCE_US: "fl oz",
    OUNCE: "oz",
    POUND: "lb",
    COUNT: "ud",
    PORTION: "ración",
    PINCH: "pizca",
    SLICE: "rebanada",
    CLOVE: "diente",
    CAN: "lata",
    PACKAGE: "paquete",
  },
  it: {
    GRAM: "g",
    KILOGRAM: "kg",
    MILLILITER: "ml",
    DECILITER: "dl",
    LITER: "l",
    TEASPOON: "cucchiaino",
    TABLESPOON: "cucchiaio",
    CUP_US: "tazza",
    FLUID_OUNCE_US: "fl oz",
    OUNCE: "oz",
    POUND: "lb",
    COUNT: "pz",
    PORTION: "porzione",
    PINCH: "pizzico",
    SLICE: "fetta",
    CLOVE: "spicchio",
    CAN: "lattina",
    PACKAGE: "confezione",
  },
  de: {
    GRAM: "g",
    KILOGRAM: "kg",
    MILLILITER: "ml",
    DECILITER: "dl",
    LITER: "l",
    TEASPOON: "TL",
    TABLESPOON: "EL",
    CUP_US: "Cup",
    FLUID_OUNCE_US: "fl oz",
    OUNCE: "oz",
    POUND: "lb",
    COUNT: "Stk",
    PORTION: "Portion",
    PINCH: "Prise",
    SLICE: "Scheibe",
    CLOVE: "Zehe",
    CAN: "Dose",
    PACKAGE: "Packung",
  },
  fr: {
    GRAM: "g",
    KILOGRAM: "kg",
    MILLILITER: "ml",
    DECILITER: "dl",
    LITER: "l",
    TEASPOON: "c. à c.",
    TABLESPOON: "c. à s.",
    CUP_US: "cup",
    FLUID_OUNCE_US: "fl oz",
    OUNCE: "oz",
    POUND: "lb",
    COUNT: "pcs",
    PORTION: "portion",
    PINCH: "pincée",
    SLICE: "tranche",
    CLOVE: "gousse",
    CAN: "boîte",
    PACKAGE: "paquet",
  },
  da: {
    GRAM: "g",
    KILOGRAM: "kg",
    MILLILITER: "ml",
    DECILITER: "dl",
    LITER: "l",
    TEASPOON: "tsk",
    TABLESPOON: "spsk",
    CUP_US: "cup",
    FLUID_OUNCE_US: "fl oz",
    OUNCE: "oz",
    POUND: "lb",
    COUNT: "stk",
    PORTION: "portion",
    PINCH: "knsp",
    SLICE: "skive",
    CLOVE: "fed",
    CAN: "dåse",
    PACKAGE: "pakke",
  },
  nb: {
    GRAM: "g",
    KILOGRAM: "kg",
    MILLILITER: "ml",
    DECILITER: "dl",
    LITER: "l",
    TEASPOON: "ts",
    TABLESPOON: "ss",
    CUP_US: "cup",
    FLUID_OUNCE_US: "fl oz",
    OUNCE: "oz",
    POUND: "lb",
    COUNT: "stk",
    PORTION: "porsjon",
    PINCH: "knivsodd",
    SLICE: "skive",
    CLOVE: "båt",
    CAN: "boks",
    PACKAGE: "pakke",
  },
  fi: {
    GRAM: "g",
    KILOGRAM: "kg",
    MILLILITER: "ml",
    DECILITER: "dl",
    LITER: "l",
    TEASPOON: "tl",
    TABLESPOON: "rkl",
    CUP_US: "cup",
    FLUID_OUNCE_US: "fl oz",
    OUNCE: "oz",
    POUND: "lb",
    COUNT: "kpl",
    PORTION: "annos",
    PINCH: "hyppysellinen",
    SLICE: "viipale",
    CLOVE: "kynsi",
    CAN: "tölkki",
    PACKAGE: "paketti",
  },
  nl: {
    GRAM: "g",
    KILOGRAM: "kg",
    MILLILITER: "ml",
    DECILITER: "dl",
    LITER: "l",
    TEASPOON: "tl",
    TABLESPOON: "el",
    CUP_US: "cup",
    FLUID_OUNCE_US: "fl oz",
    OUNCE: "oz",
    POUND: "lb",
    COUNT: "st",
    PORTION: "portie",
    PINCH: "snufje",
    SLICE: "plak",
    CLOVE: "teentje",
    CAN: "blik",
    PACKAGE: "pak",
  },
  pl: {
    GRAM: "g",
    KILOGRAM: "kg",
    MILLILITER: "ml",
    DECILITER: "dl",
    LITER: "l",
    TEASPOON: "łyżeczka",
    TABLESPOON: "łyżka",
    CUP_US: "cup",
    FLUID_OUNCE_US: "fl oz",
    OUNCE: "oz",
    POUND: "lb",
    COUNT: "szt.",
    PORTION: "porcja",
    PINCH: "szczypta",
    SLICE: "plaster",
    CLOVE: "ząbek",
    CAN: "puszka",
    PACKAGE: "opakowanie",
  },
  pt: {
    GRAM: "g",
    KILOGRAM: "kg",
    MILLILITER: "ml",
    DECILITER: "dl",
    LITER: "l",
    TEASPOON: "c. chá",
    TABLESPOON: "c. sopa",
    CUP_US: "cup",
    FLUID_OUNCE_US: "fl oz",
    OUNCE: "oz",
    POUND: "lb",
    COUNT: "un",
    PORTION: "dose",
    PINCH: "pitada",
    SLICE: "fatia",
    CLOVE: "dente",
    CAN: "lata",
    PACKAGE: "embalagem",
  },
};

let currentLanguage = "sv";
export function setUnitLanguage(language: string): void {
  currentLanguage = LABELS[language] ? language : "sv";
}

/** Kod → lokal etikett ("GRAM" → "g", "TABLESPOON" → "msk"). */
export function unitLabel(unitCode: string): string {
  return LABELS[currentLanguage]?.[unitCode] ?? LABELS.sv?.[unitCode] ?? unitCode.toLowerCase();
}

/** Fritext → kod ("msk" → TABLESPOON, "tbsp" → TABLESPOON, "st" → COUNT …). */
const PARSE: Record<string, string> = {
  g: "GRAM",
  gram: "GRAM",
  grams: "GRAM",
  kg: "KILOGRAM",
  kilo: "KILOGRAM",
  ml: "MILLILITER",
  milliliter: "MILLILITER",
  dl: "DECILITER",
  deciliter: "DECILITER",
  l: "LITER",
  liter: "LITER",
  litre: "LITER",
  tsk: "TEASPOON",
  tsp: "TEASPOON",
  teaspoon: "TEASPOON",
  msk: "TABLESPOON",
  tbsp: "TABLESPOON",
  tablespoon: "TABLESPOON",
  krm: "MILLILITER", // 1 krm = 1 ml (dokumenterad standard)
  cup: "CUP_US",
  cups: "CUP_US",
  "fl oz": "FLUID_OUNCE_US",
  floz: "FLUID_OUNCE_US",
  oz: "OUNCE",
  ounce: "OUNCE",
  lb: "POUND",
  lbs: "POUND",
  pound: "POUND",
  st: "COUNT",
  styck: "COUNT",
  pcs: "COUNT",
  pc: "COUNT",
  stk: "COUNT",
  portion: "PORTION",
  portioner: "PORTION",
  serving: "PORTION",
  nypa: "PINCH",
  pinch: "PINCH",
  skiva: "SLICE",
  skivor: "SLICE",
  slice: "SLICE",
  klyfta: "CLOVE",
  klyftor: "CLOVE",
  clove: "CLOVE",
  burk: "CAN",
  can: "CAN",
  paket: "PACKAGE",
  pkt: "PACKAGE",
  pack: "PACKAGE",
  package: "PACKAGE",
};

export function parseUnitInput(text: string): string | null {
  const key = text.trim().toLowerCase();
  if (!key) return null;
  if (LABELS.sv?.[text.trim().toUpperCase()]) return text.trim().toUpperCase();
  return PARSE[key] ?? null;
}

/** Användarens måttsystem (i18n M5) – sätts från locale-preferenserna. */
let currentSystem: MeasurementSystem = "METRIC";
export function setMeasurementSystem(system: MeasurementSystem): void {
  currentSystem = system;
}

/**
 * Kanonisk mängd -> visningssträng i användarens måttsystem (i18n-spec §9–10).
 * Lagringen är alltid kanonisk; endast visningen konverterar. "≈" markerar
 * konverterade (approximativa) värden – ärlighet före skenprecision.
 */
export function formatQuantity(quantity: number, unitCode: string): string {
  const display = KNOWN_UNITS.has(unitCode)
    ? displayQuantity(quantity, unitCode as Unit, currentSystem)
    : { value: quantity, unit: unitCode, approximate: false };
  const v = display.value;
  const rounded = Number.isInteger(v) ? String(v) : String(Math.round(v * 100) / 100);
  const prefix = display.approximate ? "≈" : "";
  return `${prefix}${rounded} ${unitLabel(String(display.unit))}`;
}

const KNOWN_UNITS = new Set(Object.keys(LABELS.sv ?? {}));
