import { describe, expect, it, afterAll } from "vitest";
import { config as loadDotenv } from "dotenv";
import path from "node:path";
import { createDatabase, closeDatabase } from "@app/database";
import { SEED_RECIPES } from "@app/database/seed";
import { verifyCandidate } from "../src/verification.js";

// Ladda monorepo-root .env (samma mönster som @app/database seed/tests)
loadDotenv({ path: path.resolve(process.cwd(), "../../.env") });

const { db } = createDatabase();

async function buildLookup() {
  const allIngs = await db.query.canonicalIngredients.findMany();
  return {
    getById(id: string) {
      return allIngs.find((i) => i.id === id) ?? undefined;
    },
  };
}

afterAll(async () => {
  await closeDatabase();
});

describe("allergen invariant", () => {
  it("varje seedat recept har allergens som matchar färsk derivering från canonical_ingredients", async () => {
    const lookup = await buildLookup();
    const seedTitles = new Set(SEED_RECIPES.map((r) => r.titleSv));
    const recipes = (await db.query.recipes.findMany()).filter((r) => seedTitles.has(r.titleSv));

    const mismatches: string[] = [];

    for (const recipe of recipes) {
      const ingredients = await db.query.recipeIngredients.findMany({
        where: (t, { eq }) => eq(t.recipeId, recipe.id),
      });
      const steps = await db.query.recipeSteps.findMany({
        where: (t, { eq }) => eq(t.recipeId, recipe.id),
      });

      if (ingredients.length === 0 || steps.length === 0) {
        // Inkompletta recept får aldrig lagras som verified i produktion.
        continue;
      }

      const candidate = {
        titleSv: recipe.titleSv,
        descriptionSv: recipe.descriptionSv,
        cuisine: recipe.cuisine,
        mealTypes: recipe.mealTypes,
        prepTimeMinutes: recipe.prepTimeMinutes,
        cookTimeMinutes: recipe.cookTimeMinutes,
        totalTimeMinutes: recipe.totalTimeMinutes,
        portions: recipe.portions,
        spiceLevel: recipe.spiceLevel,
        ingredients: ingredients.map((i) => ({
          canonicalIngredientId: i.canonicalIngredientId,
          displayNameSv: i.displayNameSv,
          quantity: i.quantity,
          unit: i.unit,
          optional: i.optional,
          note: i.note,
        })),
        steps: steps.map((s) => ({
          stepNumber: s.stepNumber,
          instructionSv: s.instructionSv,
          timerSeconds: s.timerSeconds,
          temperatureC: s.temperatureC,
          tip: s.tip,
        })),
        storageGuidanceSv: recipe.storageGuidanceSv,
        mealPrepFriendly: recipe.mealPrepFriendly,
        freezerFriendly: recipe.freezerFriendly,
        sourceType: recipe.sourceType,
        confidence: 1,
      };

      const result = await verifyCandidate(candidate as any, lookup, null);
      const derived = [...result.allergens].sort();
      const stored = [...(recipe.allergens ?? [])].sort();

      if (JSON.stringify(derived) !== JSON.stringify(stored)) {
        mismatches.push(
          `${recipe.titleSv}: stored=${JSON.stringify(stored)} derived=${JSON.stringify(derived)}`,
        );
      }
    }

    if (mismatches.length > 0) {
      console.error("Allergen mismatches:\n" + mismatches.join("\n"));
    }
    expect(mismatches).toEqual([]);
  });
});
