import {
  parseIngredient,
  unitsOfMeasure as _unitsOfMeasure,
} from "https://esm.sh/parse-ingredient@1.2.1";
import { Ingredient, IngredientGroup } from "@lib/recipeSchema.ts";
import { removeMarkdownFormatting } from "@lib/string.ts";

const customUnits = {
  tableSpoon: {
    short: "EL",
    plural: "Table Spoons",
    alternates: ["el", "EL", "Tbsp", "tbsp"],
  },
  dose: {
    short: "Dose",
    plural: "Dosen",
    alternates: ["Dose", "dose", "Dose(n)"],
  },
  pound: {
    short: "lb",
    plural: "pounds",
    alternates: ["lb", "lbs", "pound", "pounds"],
  },
  teaSpoon: {
    short: "TL",
    plural: "Tea Spoon",
    alternates: ["tl", "TL", "Tsp", "tsp", "teaspoon"],
  },
  litre: {
    short: "L",
    plural: "liters",
    alternates: ["L", "l"],
  },
  paket: {
    short: "Paket",
    plural: "Pakets",
    alternates: ["Paket", "paket"],
  },
};

export const unitsOfMeasure = {
  ..._unitsOfMeasure,
  ...customUnits,
} as const;

export function parseIngredients(
  text: string,
): (Ingredient | IngredientGroup)[] {
  const cleanText = removeMarkdownFormatting(text)
    .split("\n")
    .map((line) => line.trim().replace(/^-/, ""))
    .join("\n");

  const ingredients = parseIngredient(cleanText, {
    normalizeUOM: true,
    additionalUOMs: customUnits,
  });

  const results: (Ingredient | IngredientGroup)[] = [];
  let currentGroup: IngredientGroup | undefined;

  for (const ing of ingredients) {
    if (ing.isGroupHeader) {
      if (currentGroup) {
        results.push(currentGroup);
      }
      currentGroup = {
        name: ing.description.replace(/:$/, ""),
        items: [],
      };
    } else {
      const ingredient = {
        name: ing.description.replace(/^\s?-/, "").trim(),
        unit: ing.unitOfMeasure || "",
        quantity: ing.quantity?.toString() || ing.quantity2?.toString() || "",
        note: "",
      };

      const unit = ingredient.unit.toLowerCase() as keyof typeof unitsOfMeasure;
      if (unit in unitsOfMeasure && unit !== "cup") {
        ingredient.unit = unitsOfMeasure[unit].short;
      }

      if (!currentGroup) {
        results.push(ingredient);
      } else {
        currentGroup.items.push(ingredient);
      }
    }
  }

  if (currentGroup) {
    results.push(currentGroup);
  }

  return results;
}
