import { generateObject } from "ai";
import { z } from "zod";
import { resolveModel, type AiConfig } from "../factory";
import { dietaryTagsSchema, ingredientSchema, stepSchema } from "./recipe-schema";

const RegeneratedRecipeSchema = z.object({
  title: z.string(),
  description: z.string().optional(),
  baseServings: z.number().int().min(1).max(100),
  prepMins: z.number().int().min(0).optional(),
  cookMins: z.number().int().min(0).optional(),
  difficulty: z.enum(["easy", "medium", "hard"]).optional(),
  dietaryTags: dietaryTagsSchema.optional(),
  ingredients: z.array(ingredientSchema(z.number())),
  steps: z.array(stepSchema),
});

export type RegeneratedRecipe = z.infer<typeof RegeneratedRecipeSchema>;

const LANG: Record<string, string> = { en: "English", fr: "French" };

/** Revises a recipe draft already open in the editor per a free-text
 * instruction — "add more spice", "make it vegetarian", "double the yield".
 * Unlike adaptRecipe/suggestVariations, this never creates a new recipe or
 * variation record; it returns a full replacement draft for the caller to
 * merge into the in-progress form state, which the user still has to save. */
export async function regenerateRecipe(
  current: {
    title: string;
    description?: string | null;
    baseServings: number;
    difficulty?: string | null;
    ingredients: Array<{ rawName: string; quantity?: string | number | null; unit?: string | null }>;
    steps: Array<{ instruction: string }>;
  },
  instruction: string,
  config?: AiConfig & { language?: string }
): Promise<RegeneratedRecipe> {
  const model = resolveModel(config);
  const lang = LANG[config?.language ?? "en"] ?? "English";
  const langInstruction = lang !== "English" ? ` Write the entire recipe (title, description, ingredient names, step instructions) in ${lang}.` : "";

  const currentText = [
    `Title: ${current.title}`,
    current.description ? `Description: ${current.description}` : "",
    `Servings: ${current.baseServings}`,
    current.difficulty ? `Difficulty: ${current.difficulty}` : "",
    `Ingredients:\n${current.ingredients.map((i) => `  - ${i.quantity ? `${i.quantity} ` : ""}${i.unit ? `${i.unit} ` : ""}${i.rawName}`).join("\n")}`,
    `Steps:\n${current.steps.map((s, i) => `  ${i + 1}. ${s.instruction}`).join("\n")}`,
  ].filter(Boolean).join("\n");

  const { object } = await generateObject({
    model,
    schema: RegeneratedRecipeSchema,
    system:
      `You are revising an existing recipe draft per the user's instruction. Keep everything unchanged except what the instruction requires you to change — this is an edit, not a fresh rewrite. Return the complete updated recipe, not just the changed parts. For ingredient quantities: use numbers only, units separately.${langInstruction}`,
    prompt: `Current recipe draft:\n${currentText}\n\nInstruction: ${instruction}`,
  });

  return object;
}
