/**
 * Genereringspipeline för receptkandidater (docs/32 §2–3).
 *
 * - Gemini genererar svenska vardagsrecept KONSTRUERADE mot BEFINTLIGA
 *   canonical_ingredients.
 * - Hitta aldrig på ingredienser utanför katalogen.
 * - Varje kandidat passerar verifieringspipelinen.
 * - Ingen kandidat blir verified utan att passera alla grindar.
 */

import type { AamosClient, AamosResult } from "@app/ai-contracts";
import type {
  TaskInput,
  TaskOutput,
} from "@app/ai-contracts";
import type { RecipeCandidate, VerificationResult } from "./types.js";
import { verifyCandidate, type CanonicalIngredientLookup, type SimilarityLookup } from "./verification.js";

export interface PipelineIngredient {
  id: string;
  nameSv: string;
  category: string;
  defaultUnit: string;
  isVegan: boolean;
  isVegetarian: boolean;
  containsGluten: boolean;
  containsLactose: boolean;
  allergens: string[];
}

export interface PipelineTarget {
  mealType: string;
  mainIngredientId: string;
  dietVariant: "standard" | "vegetarian" | "vegan" | "gluten_free" | "lactose_free";
  count: number;
}

export interface PipelineOptions {
  /** Max förberedelsetid i minuter. */
  maxPrepTimeMinutes?: number;
  /** Max koktid i minuter. */
  maxCookTimeMinutes?: number;
  /** Antal portioner. */
  portions?: number;
  /** Max kryddnivå. */
  spiceLevelMax?: number;
  /** Ingredienser att undvika. */
  avoidIngredients?: string[];
  /** Locale, default sv-SE. */
  marketLocale?: string;
}

export interface PipelineResult {
  candidates: RecipeCandidate[];
  verificationResults: VerificationResult[];
  verifiedCount: number;
  unverifiedCount: number;
  rejectedCount: number;
  geminiResult: AamosResult<"GENERATE_RECIPE_CANDIDATES">;
}

/**
 * Kör genereringspipelinen: Gemini → verifiering.
 *
 * @param client AamosClient (Gemini, mock, eller HTTP)
 * @param targets Vad som ska genereras
 * @param catalog Tillgängliga canonical_ingredients
 * @param ingredients Lookup för verifiering
 * @param similarity Lookup för dedup
 * @param options Begränsningar
 */
export async function runPipeline(
  client: AamosClient,
  targets: PipelineTarget[],
  catalog: PipelineIngredient[],
  ingredients: CanonicalIngredientLookup,
  similarity: SimilarityLookup | null,
  options: PipelineOptions = {},
): Promise<PipelineResult> {
  const input: TaskInput<"GENERATE_RECIPE_CANDIDATES"> = {
    targetMatrix: targets.map((t) => ({
      mealType: t.mealType,
      mainIngredientId: t.mainIngredientId,
      dietVariant: t.dietVariant,
      count: t.count,
    })),
    canonicalIngredientsCatalog: catalog.map((i) => ({
      id: i.id,
      nameSv: i.nameSv,
      category: i.category,
      defaultUnit: i.defaultUnit as import("@app/shared-types").Unit,
      isVegan: i.isVegan,
      isVegetarian: i.isVegetarian,
      containsGluten: i.containsGluten,
      containsLactose: i.containsLactose,
      allergens: i.allergens,
    })),
    constraints: {
      maxPrepTimeMinutes: options.maxPrepTimeMinutes ?? 60,
      maxCookTimeMinutes: options.maxCookTimeMinutes ?? 45,
      portions: options.portions ?? 4,
      spiceLevelMax: options.spiceLevelMax ?? 3,
      avoidIngredients: options.avoidIngredients ?? [],
    },
    marketLocale: options.marketLocale ?? "sv-SE",
  };

  const geminiResult = await client.runTask("GENERATE_RECIPE_CANDIDATES", input);

  if (geminiResult.status !== "ok" || !geminiResult.output) {
    return {
      candidates: [],
      verificationResults: [],
      verifiedCount: 0,
      unverifiedCount: 0,
      rejectedCount: 0,
      geminiResult,
    };
  }

  const output = geminiResult.output as TaskOutput<"GENERATE_RECIPE_CANDIDATES">;

  // Mappa Gemini-output till interna typer
  const candidates: RecipeCandidate[] = output.candidates.map((c, idx) => ({
    titleSv: c.titleSv,
    descriptionSv: c.descriptionSv,
    cuisine: c.cuisine,
    mealTypes: c.mealTypes,
    prepTimeMinutes: c.prepTimeMinutes,
    cookTimeMinutes: c.cookTimeMinutes,
    totalTimeMinutes: c.prepTimeMinutes + c.cookTimeMinutes,
    portions: c.portions,
    spiceLevel: c.spiceLevel,
    ingredients: c.ingredients.map((ing) => ({
      canonicalIngredientId: ing.canonicalIngredientId,
      displayNameSv: ing.displayNameSv,
      quantity: ing.quantity,
      unit: ing.unit,
      optional: ing.optional,
      note: ing.note,
    })),
    steps: c.steps.map((s, sIdx) => ({
      stepNumber: sIdx + 1,
      instructionSv: s.instructionSv,
      timerSeconds: s.timerSeconds,
      temperatureC: s.temperatureC,
      tip: s.tip,
    })),
    storageGuidanceSv: c.storageGuidanceSv,
    mealPrepFriendly: c.mealPrepFriendly,
    freezerFriendly: c.freezerFriendly,
    sourceType: "ai_generated" as const,
    confidence: c.confidence,
  }));

  // Kör verifieringspipelinen
  const verificationResults = await Promise.all(
    candidates.map((c) => verifyCandidate(c, ingredients, similarity)),
  );

  const verifiedCount = verificationResults.filter((r) => r.status === "verified").length;
  const unverifiedCount = verificationResults.filter((r) => r.status === "unverified").length;
  const rejectedCount = verificationResults.filter((r) => r.status === "rejected").length;

  return {
    candidates,
    verificationResults,
    verifiedCount,
    unverifiedCount,
    rejectedCount,
    geminiResult,
  };
}
