import recipeSchema from "@lib/recipeSchema.ts";
import { parseIngredients } from "@lib/parseIngredient.ts";

export function parseJsonLdToRecipeSchema(jsonLdContent: string) {
  try {
    let data = JSON.parse(jsonLdContent);

    const image = data.image;

    // Handle nested data inside `mainEntity`
    if (data["mainEntity"]) {
      data = data["mainEntity"];
    }

    // Ensure it's a valid Recipe type
    if (
      typeof data !== "object" || !data["@type"] || data["@type"] !== "Recipe"
    ) {
      return;
    }

    // Map and parse ingredients into the new schema
    const ingredients = parseIngredients(
      data?.recipeIngredient?.join("\n") || "",
    );

    const instructions = Array.isArray(data.recipeInstructions)
      ? data.recipeInstructions.map((instr) => {
        if (typeof instr === "string") return instr;
        if (typeof instr === "object" && instr.text) return instr.text;
        return "";
      }).filter((instr) => instr.trim() !== "")
      : [];

    // Parse servings
    const servings = parseServings(data.recipeYield);

    // Parse times
    const prepTime = parseDuration(data.prepTime);
    const cookTime = parseDuration(data.cookTime);
    const totalTime = parseDuration(data.totalTime);

    // Extract tags
    const tags = data.keywords
      ? Array.isArray(data.keywords)
        ? data.keywords
        : data.keywords.split(",").map((tag: string) => tag.trim())
      : [];

    // Build the recipe object
    const recipe = {
      title: data.name || "Unnamed Recipe",
      image: pickImage(image || data.image || ""),
      author: Array.isArray(data.author)
        ? data.author.map((a: any) => a.name).join(", ")
        : data.author?.name || "",
      description: data.description || "",
      ingredients,
      instructions,
      servings,
      prepTime,
      cookTime,
      totalTime,
      tags,
      notes: data.notes || [],
    };

    // Validate against the schema
    return recipeSchema.parse(recipe);
  } catch (error) {
    console.error("Invalid JSON-LD content or parsing error:", error);
    return undefined;
  }
}

function pickImage(images: string | string[]): string {
  if (Array.isArray(images)) {
    return images[0];
  }
  return images;
}

function parseServings(servingsData: any): number {
  if (typeof servingsData === "string") {
    const match = servingsData.match(/\d+/);
    return match ? parseInt(match[0], 10) : 1;
  }
  if (typeof servingsData === "number") {
    return servingsData;
  }
  return 1;
}

function parseDuration(duration: string | undefined): number {
  if (!duration) return 0;

  // Matches ISO 8601 durations (e.g., "PT30M" -> 30 minutes)
  const match = duration.match(/PT(?:(\d+)H)?(?:(\d+)M)?/);
  const hours = match?.[1] ? parseInt(match[1], 10) : 0;
  const minutes = match?.[2] ? parseInt(match[2], 10) : 0;

  return hours * 60 + minutes;
}
