import { config as loadDotenv } from "dotenv";
import { existsSync } from "node:fs";
import path from "node:path";

// Ladda .env från paketet ELLER monorepo-roten (pnpm --filter sätter cwd till paketet).
for (const candidate of [".env", "../.env", "../../.env"]) {
  const p = path.resolve(process.cwd(), candidate);
  if (existsSync(p)) {
    loadDotenv({ path: p });
    break;
  }
}
import {
  computeRecipeNutrition,
  toGrams,
  type IngredientNutritionSource,
} from "@app/nutrition-engine";
import { BRAND, type Allergen, type RecipeDNA } from "@app/shared-types";
import { createDatabase } from "../client.js";
import * as schema from "../schema/index.js";
import { SEED_INGREDIENTS } from "./data/ingredients.js";
import INGREDIENT_TRANSLATIONS from "./data/ingredient-translations.json" with { type: "json" };
import { SEED_RECIPES, type SeedRecipe } from "./data/recipes.js";
import { SEED_SUBSTITUTIONS } from "./data/substitutions.js";
import { SEED_SEASON_EVENTS } from "./data/seasonEvents.js";

/**
 * Seed-körning. Idempotent: onConflictDoNothing/Update där det är säkert.
 *
 * Näring, allergener och kostnad för recepten beräknas HÄR, deterministiskt,
 * ur ingredienserna (spec §61.1–2) – aldrig hårdkodade och aldrig från AI.
 */
async function main() {
  const { db, pool } = createDatabase();
  console.log("[seed] Startar …");

  // 1. Kanoniska ingredienser
  for (const ing of SEED_INGREDIENTS) {
    await db
      .insert(schema.canonicalIngredients)
      .values({
        id: ing.id,
        nameSv: ing.nameSv,
        nameEn: ing.nameEn,
        aliases: ing.aliases,
        category: ing.category,
        defaultUnit: ing.defaultUnit,
        densityGPerMl: ing.densityGPerMl ?? null,
        gramsPerPiece: ing.gramsPerPiece ?? null,
        allergens: ing.allergens,
        isVegan: ing.isVegan,
        isVegetarian: ing.isVegetarian,
        containsGluten: ing.containsGluten,
        containsLactose: ing.containsLactose,
        isPork: ing.isPork,
        isBeef: ing.isBeef,
        isAlcohol: ing.isAlcohol,
        nutritionPer100: ing.nutritionPer100,
        nutritionProvenance: ing.nutritionProvenance,
        peakSeasons: ing.peakSeasons,
        shelfLifeGuidance: ing.shelfLifeGuidance ?? null,
        defaultPriceMinorPerKg: ing.defaultPriceMinorPerKg ?? null,
      })
      .onConflictDoUpdate({
        target: schema.canonicalIngredients.id,
        set: {
          nameSv: ing.nameSv,
          nutritionPer100: ing.nutritionPer100,
          updatedAt: new Date(),
        },
      });
  }
  console.log(`[seed] ${SEED_INGREDIENTS.length} ingredienser`);

  // 1b. Ingrediensöversättningar (i18n M2 + D-031): en ur nameEn; es/it/de/fr
  // ur ingredient-translations.json. Rader per språk – aldrig nya kolumner.
  // Seed-källa = publicerad direkt; native-granskning rekommenderas före lansering.
  const translationRows: { ingredientId: string; languageTag: string; name: string }[] =
    SEED_INGREDIENTS.map((ing) => ({ ingredientId: ing.id, languageTag: "en", name: ing.nameEn }));
  for (const [languageTag, names] of Object.entries(
    INGREDIENT_TRANSLATIONS as Record<string, Record<string, string>>,
  )) {
    for (const [ingredientId, name] of Object.entries(names)) {
      translationRows.push({ ingredientId, languageTag, name });
    }
  }
  for (const row of translationRows) {
    await db
      .insert(schema.ingredientTranslations)
      .values({ ...row, aliases: [], source: "seed", status: "published" })
      .onConflictDoUpdate({
        target: [
          schema.ingredientTranslations.ingredientId,
          schema.ingredientTranslations.languageTag,
        ],
        set: { name: row.name, updatedAt: new Date() },
      });
  }
  console.log(`[seed] ${translationRows.length} ingrediensöversättningar (11 språk)`);

  // 1c. Enhetsetiketter per språk (i18n M2). Visning – lagring är alltid koderna.
  const UNIT_LABELS: Record<string, Record<string, { abbr: string; name: string }>> = {
    sv: {
      GRAM: { abbr: "g", name: "gram" },
      KILOGRAM: { abbr: "kg", name: "kilogram" },
      MILLILITER: { abbr: "ml", name: "milliliter" },
      DECILITER: { abbr: "dl", name: "deciliter" },
      LITER: { abbr: "l", name: "liter" },
      TEASPOON: { abbr: "tsk", name: "tesked" },
      TABLESPOON: { abbr: "msk", name: "matsked" },
      CUP_US: { abbr: "cup", name: "cup (US)" },
      FLUID_OUNCE_US: { abbr: "fl oz", name: "fluid ounce (US)" },
      OUNCE: { abbr: "oz", name: "ounce" },
      POUND: { abbr: "lb", name: "pound" },
      COUNT: { abbr: "st", name: "styck" },
      PORTION: { abbr: "portion", name: "portion" },
      PINCH: { abbr: "krm", name: "kryddmått" },
      SLICE: { abbr: "skiva", name: "skiva" },
      CLOVE: { abbr: "klyfta", name: "klyfta" },
      CAN: { abbr: "burk", name: "burk" },
      PACKAGE: { abbr: "paket", name: "paket" },
    },
    en: {
      GRAM: { abbr: "g", name: "gram" },
      KILOGRAM: { abbr: "kg", name: "kilogram" },
      MILLILITER: { abbr: "ml", name: "milliliter" },
      DECILITER: { abbr: "dl", name: "deciliter" },
      LITER: { abbr: "l", name: "liter" },
      TEASPOON: { abbr: "tsp", name: "teaspoon" },
      TABLESPOON: { abbr: "tbsp", name: "tablespoon" },
      CUP_US: { abbr: "cup", name: "cup (US)" },
      FLUID_OUNCE_US: { abbr: "fl oz", name: "fluid ounce (US)" },
      OUNCE: { abbr: "oz", name: "ounce" },
      POUND: { abbr: "lb", name: "pound" },
      COUNT: { abbr: "pcs", name: "pieces" },
      PORTION: { abbr: "serving", name: "serving" },
      PINCH: { abbr: "pinch", name: "pinch" },
      SLICE: { abbr: "slice", name: "slice" },
      CLOVE: { abbr: "clove", name: "clove" },
      CAN: { abbr: "can", name: "can" },
      PACKAGE: { abbr: "pack", name: "package" },
    },
    es: {
      GRAM: { abbr: "g", name: "gramo" },
      KILOGRAM: { abbr: "kg", name: "kilogramo" },
      MILLILITER: { abbr: "ml", name: "mililitro" },
      DECILITER: { abbr: "dl", name: "decilitro" },
      LITER: { abbr: "l", name: "litro" },
      TEASPOON: { abbr: "cdta", name: "cucharadita" },
      TABLESPOON: { abbr: "cda", name: "cucharada" },
      CUP_US: { abbr: "taza", name: "taza (US)" },
      FLUID_OUNCE_US: { abbr: "fl oz", name: "onza líquida (US)" },
      OUNCE: { abbr: "oz", name: "onza" },
      POUND: { abbr: "lb", name: "libra" },
      COUNT: { abbr: "ud", name: "unidad" },
      PORTION: { abbr: "ración", name: "ración" },
      PINCH: { abbr: "pizca", name: "pizca" },
      SLICE: { abbr: "rebanada", name: "rebanada" },
      CLOVE: { abbr: "diente", name: "diente" },
      CAN: { abbr: "lata", name: "lata" },
      PACKAGE: { abbr: "paquete", name: "paquete" },
    },
    it: {
      GRAM: { abbr: "g", name: "grammo" },
      KILOGRAM: { abbr: "kg", name: "chilogrammo" },
      MILLILITER: { abbr: "ml", name: "millilitro" },
      DECILITER: { abbr: "dl", name: "decilitro" },
      LITER: { abbr: "l", name: "litro" },
      TEASPOON: { abbr: "cucchiaino", name: "cucchiaino" },
      TABLESPOON: { abbr: "cucchiaio", name: "cucchiaio" },
      CUP_US: { abbr: "tazza", name: "tazza (US)" },
      FLUID_OUNCE_US: { abbr: "fl oz", name: "oncia liquida (US)" },
      OUNCE: { abbr: "oz", name: "oncia" },
      POUND: { abbr: "lb", name: "libbra" },
      COUNT: { abbr: "pz", name: "pezzo" },
      PORTION: { abbr: "porzione", name: "porzione" },
      PINCH: { abbr: "pizzico", name: "pizzico" },
      SLICE: { abbr: "fetta", name: "fetta" },
      CLOVE: { abbr: "spicchio", name: "spicchio" },
      CAN: { abbr: "lattina", name: "lattina" },
      PACKAGE: { abbr: "confezione", name: "confezione" },
    },
    de: {
      GRAM: { abbr: "g", name: "Gramm" },
      KILOGRAM: { abbr: "kg", name: "Kilogramm" },
      MILLILITER: { abbr: "ml", name: "Milliliter" },
      DECILITER: { abbr: "dl", name: "Deziliter" },
      LITER: { abbr: "l", name: "Liter" },
      TEASPOON: { abbr: "TL", name: "Teelöffel" },
      TABLESPOON: { abbr: "EL", name: "Esslöffel" },
      CUP_US: { abbr: "Cup", name: "Cup (US)" },
      FLUID_OUNCE_US: { abbr: "fl oz", name: "Flüssigunze (US)" },
      OUNCE: { abbr: "oz", name: "Unze" },
      POUND: { abbr: "lb", name: "Pfund" },
      COUNT: { abbr: "Stk", name: "Stück" },
      PORTION: { abbr: "Portion", name: "Portion" },
      PINCH: { abbr: "Prise", name: "Prise" },
      SLICE: { abbr: "Scheibe", name: "Scheibe" },
      CLOVE: { abbr: "Zehe", name: "Zehe" },
      CAN: { abbr: "Dose", name: "Dose" },
      PACKAGE: { abbr: "Packung", name: "Packung" },
    },
    fr: {
      GRAM: { abbr: "g", name: "gramme" },
      KILOGRAM: { abbr: "kg", name: "kilogramme" },
      MILLILITER: { abbr: "ml", name: "millilitre" },
      DECILITER: { abbr: "dl", name: "décilitre" },
      LITER: { abbr: "l", name: "litre" },
      TEASPOON: { abbr: "c. à c.", name: "cuillère à café" },
      TABLESPOON: { abbr: "c. à s.", name: "cuillère à soupe" },
      CUP_US: { abbr: "cup", name: "cup (US)" },
      FLUID_OUNCE_US: { abbr: "fl oz", name: "once liquide (US)" },
      OUNCE: { abbr: "oz", name: "once" },
      POUND: { abbr: "lb", name: "livre" },
      COUNT: { abbr: "pcs", name: "pièce" },
      PORTION: { abbr: "portion", name: "portion" },
      PINCH: { abbr: "pincée", name: "pincée" },
      SLICE: { abbr: "tranche", name: "tranche" },
      CLOVE: { abbr: "gousse", name: "gousse" },
      CAN: { abbr: "boîte", name: "boîte" },
      PACKAGE: { abbr: "paquet", name: "paquet" },
    },
    da: {
      GRAM: { abbr: "g", name: "gram" },
      KILOGRAM: { abbr: "kg", name: "kilogram" },
      MILLILITER: { abbr: "ml", name: "milliliter" },
      DECILITER: { abbr: "dl", name: "deciliter" },
      LITER: { abbr: "l", name: "liter" },
      TEASPOON: { abbr: "tsk", name: "teskefuld" },
      TABLESPOON: { abbr: "spsk", name: "spiseskefuld" },
      CUP_US: { abbr: "cup", name: "cup (US)" },
      FLUID_OUNCE_US: { abbr: "fl oz", name: "fluid ounce (US)" },
      OUNCE: { abbr: "oz", name: "ounce" },
      POUND: { abbr: "lb", name: "pund" },
      COUNT: { abbr: "stk", name: "styk" },
      PORTION: { abbr: "portion", name: "portion" },
      PINCH: { abbr: "knsp", name: "knivspids" },
      SLICE: { abbr: "skive", name: "skive" },
      CLOVE: { abbr: "fed", name: "fed" },
      CAN: { abbr: "dåse", name: "dåse" },
      PACKAGE: { abbr: "pakke", name: "pakke" },
    },
    nb: {
      GRAM: { abbr: "g", name: "gram" },
      KILOGRAM: { abbr: "kg", name: "kilogram" },
      MILLILITER: { abbr: "ml", name: "milliliter" },
      DECILITER: { abbr: "dl", name: "desiliter" },
      LITER: { abbr: "l", name: "liter" },
      TEASPOON: { abbr: "ts", name: "teskje" },
      TABLESPOON: { abbr: "ss", name: "spiseskje" },
      CUP_US: { abbr: "cup", name: "cup (US)" },
      FLUID_OUNCE_US: { abbr: "fl oz", name: "fluid ounce (US)" },
      OUNCE: { abbr: "oz", name: "unse" },
      POUND: { abbr: "lb", name: "pund" },
      COUNT: { abbr: "stk", name: "stykk" },
      PORTION: { abbr: "porsjon", name: "porsjon" },
      PINCH: { abbr: "knivsodd", name: "knivsodd" },
      SLICE: { abbr: "skive", name: "skive" },
      CLOVE: { abbr: "båt", name: "båt" },
      CAN: { abbr: "boks", name: "boks" },
      PACKAGE: { abbr: "pakke", name: "pakke" },
    },
    fi: {
      GRAM: { abbr: "g", name: "gramma" },
      KILOGRAM: { abbr: "kg", name: "kilogramma" },
      MILLILITER: { abbr: "ml", name: "millilitra" },
      DECILITER: { abbr: "dl", name: "desilitra" },
      LITER: { abbr: "l", name: "litra" },
      TEASPOON: { abbr: "tl", name: "teelusikka" },
      TABLESPOON: { abbr: "rkl", name: "ruokalusikka" },
      CUP_US: { abbr: "cup", name: "cup (US)" },
      FLUID_OUNCE_US: { abbr: "fl oz", name: "nesteunssi (US)" },
      OUNCE: { abbr: "oz", name: "unssi" },
      POUND: { abbr: "lb", name: "pauna" },
      COUNT: { abbr: "kpl", name: "kappale" },
      PORTION: { abbr: "annos", name: "annos" },
      PINCH: { abbr: "hyppysellinen", name: "hyppysellinen" },
      SLICE: { abbr: "viipale", name: "viipale" },
      CLOVE: { abbr: "kynsi", name: "kynsi" },
      CAN: { abbr: "tölkki", name: "tölkki" },
      PACKAGE: { abbr: "paketti", name: "paketti" },
    },
    nl: {
      GRAM: { abbr: "g", name: "gram" },
      KILOGRAM: { abbr: "kg", name: "kilogram" },
      MILLILITER: { abbr: "ml", name: "milliliter" },
      DECILITER: { abbr: "dl", name: "deciliter" },
      LITER: { abbr: "l", name: "liter" },
      TEASPOON: { abbr: "tl", name: "theelepel" },
      TABLESPOON: { abbr: "el", name: "eetlepel" },
      CUP_US: { abbr: "cup", name: "cup (US)" },
      FLUID_OUNCE_US: { abbr: "fl oz", name: "fluid ounce (US)" },
      OUNCE: { abbr: "oz", name: "ounce" },
      POUND: { abbr: "lb", name: "pond" },
      COUNT: { abbr: "st", name: "stuk" },
      PORTION: { abbr: "portie", name: "portie" },
      PINCH: { abbr: "snufje", name: "snufje" },
      SLICE: { abbr: "plak", name: "plak" },
      CLOVE: { abbr: "teentje", name: "teentje" },
      CAN: { abbr: "blik", name: "blik" },
      PACKAGE: { abbr: "pak", name: "pak" },
    },
    pl: {
      GRAM: { abbr: "g", name: "gram" },
      KILOGRAM: { abbr: "kg", name: "kilogram" },
      MILLILITER: { abbr: "ml", name: "mililitr" },
      DECILITER: { abbr: "dl", name: "decylitr" },
      LITER: { abbr: "l", name: "litr" },
      TEASPOON: { abbr: "łyżeczka", name: "łyżeczka" },
      TABLESPOON: { abbr: "łyżka", name: "łyżka" },
      CUP_US: { abbr: "cup", name: "cup (US)" },
      FLUID_OUNCE_US: { abbr: "fl oz", name: "uncja płynu (US)" },
      OUNCE: { abbr: "oz", name: "uncja" },
      POUND: { abbr: "lb", name: "funt" },
      COUNT: { abbr: "szt.", name: "sztuka" },
      PORTION: { abbr: "porcja", name: "porcja" },
      PINCH: { abbr: "szczypta", name: "szczypta" },
      SLICE: { abbr: "plaster", name: "plaster" },
      CLOVE: { abbr: "ząbek", name: "ząbek" },
      CAN: { abbr: "puszka", name: "puszka" },
      PACKAGE: { abbr: "opakowanie", name: "opakowanie" },
    },
    pt: {
      GRAM: { abbr: "g", name: "grama" },
      KILOGRAM: { abbr: "kg", name: "quilograma" },
      MILLILITER: { abbr: "ml", name: "mililitro" },
      DECILITER: { abbr: "dl", name: "decilitro" },
      LITER: { abbr: "l", name: "litro" },
      TEASPOON: { abbr: "c. chá", name: "colher de chá" },
      TABLESPOON: { abbr: "c. sopa", name: "colher de sopa" },
      CUP_US: { abbr: "cup", name: "cup (US)" },
      FLUID_OUNCE_US: { abbr: "fl oz", name: "onça líquida (US)" },
      OUNCE: { abbr: "oz", name: "onça" },
      POUND: { abbr: "lb", name: "libra" },
      COUNT: { abbr: "un", name: "unidade" },
      PORTION: { abbr: "dose", name: "dose" },
      PINCH: { abbr: "pitada", name: "pitada" },
      SLICE: { abbr: "fatia", name: "fatia" },
      CLOVE: { abbr: "dente", name: "dente" },
      CAN: { abbr: "lata", name: "lata" },
      PACKAGE: { abbr: "embalagem", name: "embalagem" },
    },
  };
  let unitLabelCount = 0;
  for (const [languageTag, labels] of Object.entries(UNIT_LABELS)) {
    for (const [unitCode, label] of Object.entries(labels)) {
      await db
        .insert(schema.unitTranslations)
        .values({
          unitCode: unitCode as (typeof schema.unitTranslations.$inferInsert)["unitCode"],
          languageTag,
          abbreviation: label.abbr,
          name: label.name,
        })
        .onConflictDoUpdate({
          target: [schema.unitTranslations.unitCode, schema.unitTranslations.languageTag],
          set: { abbreviation: label.abbr, name: label.name },
        });
      unitLabelCount++;
    }
  }
  console.log(`[seed] ${unitLabelCount} enhetsetiketter (12 språk)`);

  // 1d. Marknadsprofiler för näringsvisning + allergenframhävning (i18n M6).
  const NUTRITION_PROFILES = [
    {
      regionCode: "EU",
      energyDisplay: "both" as const,
      saltDisplay: "salt" as const,
      energyLabelKey: "nutrition.energy",
    },
    {
      regionCode: "SE",
      energyDisplay: "both" as const,
      saltDisplay: "salt" as const,
      energyLabelKey: "nutrition.energy",
    },
    {
      regionCode: "GB",
      energyDisplay: "both" as const,
      saltDisplay: "salt" as const,
      energyLabelKey: "nutrition.energy",
    },
    {
      regionCode: "US",
      energyDisplay: "kcal" as const,
      saltDisplay: "sodium" as const,
      energyLabelKey: "nutrition.calories",
    },
    {
      regionCode: "CA",
      energyDisplay: "kcal" as const,
      saltDisplay: "sodium" as const,
      energyLabelKey: "nutrition.calories",
    },
  ];
  for (const p of NUTRITION_PROFILES) {
    await db
      .insert(schema.nutritionDisplayProfiles)
      .values(p)
      .onConflictDoUpdate({
        target: schema.nutritionDisplayProfiles.regionCode,
        set: { ...p, updatedAt: new Date() },
      });
  }
  // EU/EES + GB: 14 deklarationspliktiga. US (FDA Big 9): utan selleri/senap/lupin/
  // sulfiter/blötdjur. CA (Health Canada): som EU utan selleri och lupin.
  const EU14 = [
    "gluten",
    "crustaceans",
    "eggs",
    "fish",
    "peanuts",
    "soy",
    "milk",
    "tree_nuts",
    "celery",
    "mustard",
    "sesame",
    "sulphites",
    "lupin",
    "molluscs",
  ] as const;
  const US9 = [
    "gluten",
    "crustaceans",
    "eggs",
    "fish",
    "peanuts",
    "soy",
    "milk",
    "tree_nuts",
    "sesame",
  ] as const;
  const CA = [
    "gluten",
    "crustaceans",
    "eggs",
    "fish",
    "peanuts",
    "soy",
    "milk",
    "tree_nuts",
    "mustard",
    "sesame",
    "sulphites",
    "molluscs",
  ] as const;
  const MARKET_ALLERGENS: Record<string, readonly string[]> = {
    EU: EU14,
    SE: EU14,
    GB: EU14,
    US: US9,
    CA,
  };
  let ruleCount = 0;
  for (const [regionCode, allergens] of Object.entries(MARKET_ALLERGENS)) {
    for (const allergen of allergens) {
      await db
        .insert(schema.allergenMarketRules)
        .values({ regionCode, allergen: allergen as (typeof EU14)[number], mustHighlight: true })
        .onConflictDoNothing();
      ruleCount++;
    }
  }
  console.log(`[seed] ${NUTRITION_PROFILES.length} näringsprofiler + ${ruleCount} allergenregler`);

  // Uppslagskarta för beräkningar
  const ingredientMap = new Map(
    SEED_INGREDIENTS.map((i) => [
      i.id,
      {
        nutritionPer100: i.nutritionPer100,
        densityGPerMl: i.densityGPerMl ?? null,
        gramsPerPiece: i.gramsPerPiece ?? null,
        allergens: i.allergens,
        priceMinorPerKg: i.defaultPriceMinorPerKg ?? null,
      },
    ]),
  );

  // 2. Source registry-post för redaktionella recept (spec §15)
  const [registry] = await db
    .insert(schema.recipeSourceRegistry)
    .values({
      sourceName: `${BRAND.name} Redaktion`,
      license: "proprietary",
      rightToStore: true,
      rightToModify: true,
      rightToDisplay: true,
      attributionRequired: false,
      commercialUse: true,
      notes: "Egna originalrecept. Fullständiga rättigheter.",
    })
    .returning();

  // 3. Recept i två pass (varianter behöver grundreceptets id)
  const slugToId = new Map<string, string>();
  const basePass = SEED_RECIPES.filter((r) => !r.variantOfSlug);
  const variantPass = SEED_RECIPES.filter((r) => r.variantOfSlug);

  for (const recipe of [...basePass, ...variantPass]) {
    const id = await insertRecipe(db, recipe, ingredientMap, registry?.id ?? null, slugToId);
    slugToId.set(recipe.slug, id);
  }
  console.log(`[seed] ${SEED_RECIPES.length} recept`);

  // 4. Substitutioner
  for (const sub of SEED_SUBSTITUTIONS) {
    await db
      .insert(schema.substitutions)
      .values({
        id: sub.id,
        fromIngredientId: sub.from,
        toIngredientId: sub.to,
        ratio: sub.ratio,
        instructionsSv: sub.instructionsSv ?? null,
        bestFor: sub.bestFor,
        notRecommendedFor: sub.notRecommendedFor,
        flavorImpactSv: sub.flavorImpactSv ?? null,
        textureImpactSv: sub.textureImpactSv ?? null,
        priority: sub.priority ?? 0,
      })
      .onConflictDoNothing();
  }
  console.log(`[seed] ${SEED_SUBSTITUTIONS.length} substitutioner`);

  // 5. Säsongsevents
  for (const ev of SEED_SEASON_EVENTS) {
    await db
      .insert(schema.seasonEvents)
      .values({
        id: ev.id,
        slug: ev.slug,
        nameSv: ev.nameSv,
        market: ev.market,
        dateRule: ev.dateRule,
        leadDays: ev.leadDays,
        foodTags: ev.foodTags,
        recipeSlugs: ev.recipeSlugs,
        priority: ev.priority,
        active: true,
      })
      .onConflictDoNothing();
  }
  console.log(`[seed] ${SEED_SEASON_EVENTS.length} säsongsevents`);

  // 6. Feature flags – Launch Core på, Advanced bakom flaggor (spec §1, Del 3)
  const flags: Array<{ key: string; enabled: boolean; descriptionSv: string }> = [
    { key: "community_publishing", enabled: false, descriptionSv: "Publicering av användarrecept" },
    { key: "week_plan_ai", enabled: true, descriptionSv: "AI-assisterad veckoplan" },
    {
      key: "plate_photo_analysis",
      enabled: true,
      descriptionSv: "Tallriksfoto och portionsuppskattning",
    },
    { key: "receipt_scanning", enabled: true, descriptionSv: "Kvittoskanning" },
    { key: "pantry_forecast", enabled: false, descriptionSv: "Pantry Forecast-notiser" },
    { key: "health_integration", enabled: false, descriptionSv: "Apple Health / Health Connect" },
    { key: "weather_context", enabled: false, descriptionSv: "Väderbaserade förslag" },
    { key: "creator_rankings", enabled: false, descriptionSv: "Topplistor och gamification" },
    { key: "food_memories", enabled: false, descriptionSv: "Långsiktiga matminnen" },
    { key: "voice_input", enabled: false, descriptionSv: "Röstinmatning" },
    { key: "ai_rerank", enabled: false, descriptionSv: "AAMOS-omrankning av rekommendationer" },
  ];
  for (const flag of flags) {
    await db
      .insert(schema.featureFlags)
      .values({
        key: flag.key,
        enabled: flag.enabled,
        descriptionSv: flag.descriptionSv,
        rolloutPercent: 100,
      })
      .onConflictDoNothing();
  }
  console.log(`[seed] ${flags.length} feature flags`);

  console.log("[seed] Klart.");
  await pool.end();
}

type IngredientCalcInfo = {
  nutritionPer100: IngredientNutritionSource["nutritionPer100"];
  densityGPerMl: number | null;
  gramsPerPiece: number | null;
  allergens: Allergen[];
  priceMinorPerKg: number | null;
};

async function insertRecipe(
  db: ReturnType<typeof createDatabase>["db"],
  recipe: SeedRecipe,
  ingredientMap: Map<string, IngredientCalcInfo>,
  sourceRegistryId: string | null,
  slugToId: Map<string, string>,
): Promise<string> {
  // Deterministisk näringsberäkning
  const sources = new Map<string, IngredientNutritionSource>();
  for (const ri of recipe.ingredients) {
    const info = ingredientMap.get(ri.ing);
    if (!info) throw new Error(`Recept ${recipe.slug}: okänd ingrediens ${ri.ing}`);
    sources.set(ri.ing, {
      nutritionPer100: info.nutritionPer100,
      densityGPerMl: info.densityGPerMl,
      gramsPerPiece: info.gramsPerPiece,
    });
  }
  const calcIngredients = recipe.ingredients.map((ri) => ({
    canonicalIngredientId: ri.ing,
    quantity: ri.qty,
    unit: ri.unit,
    optional: ri.optional ?? false,
  }));
  const nutrition = computeRecipeNutrition(calcIngredients, recipe.portions, sources);
  if (nutrition.uncomputableIngredientIds.length > 0) {
    throw new Error(
      `Recept ${recipe.slug}: kunde inte beräkna näring för ${nutrition.uncomputableIngredientIds.join(", ")}`,
    );
  }

  // Deterministisk allergenhärledning
  const allergens = new Set<Allergen>();
  for (const ri of recipe.ingredients) {
    if (ri.optional) continue;
    for (const a of ingredientMap.get(ri.ing)?.allergens ?? []) allergens.add(a);
  }

  // Kostnadsuppskattning ur schablonpriser
  let costTotal = 0;
  let costComputable = true;
  for (const ri of recipe.ingredients) {
    if (ri.optional) continue;
    const info = ingredientMap.get(ri.ing)!;
    const grams = toGrams(ri.qty, ri.unit, {
      densityGPerMl: info.densityGPerMl,
      gramsPerPiece: info.gramsPerPiece,
    });
    if (grams == null || info.priceMinorPerKg == null) {
      costComputable = false;
      continue;
    }
    costTotal += (grams / 1000) * info.priceMinorPerKg;
  }
  // costTotal är i minor units (priceMinorPerKg) – avrunda till heltal per portion.
  const costPerPortion =
    costComputable && recipe.portions > 0 ? Math.round(costTotal / recipe.portions) : null;

  const dna: RecipeDNA = {
    cuisine: recipe.cuisine,
    ...(recipe.dnaProtein ? { protein: recipe.dnaProtein } : {}),
    ...(recipe.dnaCarb ? { carbohydrate: recipe.dnaCarb } : {}),
    vegetables: recipe.dnaVegetables,
    flavorProfile: recipe.dnaFlavor,
    spiceLevel: recipe.spiceLevel,
    method: recipe.methods[0] ?? "stovetop",
    timeMinutes: recipe.prepMin + recipe.cookMin,
    calories: nutrition.perPortion.kcal,
    proteinGrams: Math.round(nutrition.perPortion.proteinG),
  };

  const variantOfRecipeId = recipe.variantOfSlug
    ? (slugToId.get(recipe.variantOfSlug) ?? null)
    : null;

  const [row] = await db
    .insert(schema.recipes)
    .values({
      slug: recipe.slug,
      titleSv: recipe.titleSv,
      descriptionSv: recipe.descriptionSv,
      country: recipe.country ?? null,
      cuisine: recipe.cuisine,
      mealTypes: recipe.mealTypes,
      tags: recipe.tags,
      methods: recipe.methods,
      equipment: recipe.equipment,
      difficulty: recipe.difficulty,
      prepTimeMinutes: recipe.prepMin,
      cookTimeMinutes: recipe.cookMin,
      totalTimeMinutes: recipe.prepMin + recipe.cookMin,
      portions: recipe.portions,
      nutritionPerPortion: nutrition.perPortion,
      allergens: [...allergens].sort(),
      spiceLevel: recipe.spiceLevel,
      estimatedCostMinorPerPortion: costPerPortion,
      storageGuidanceSv: recipe.storageGuidanceSv ?? null,
      mealPrepFriendly: recipe.mealPrepFriendly,
      freezerFriendly: recipe.freezerFriendly,
      peakSeasons: recipe.peakSeasons,
      holidayTags: recipe.holidayTags,
      dna,
      variantType: recipe.variantType ?? "standard",
      variantOfRecipeId,
      status: "published",
      verificationStatus: "editorial",
      sourceType: "own_editorial",
      sourceRegistryId,
      creatorDisplayName: `${BRAND.name} Redaktion`,
    })
    .onConflictDoUpdate({
      target: schema.recipes.slug,
      set: {
        nutritionPerPortion: nutrition.perPortion,
        allergens: [...allergens].sort(),
        dna,
        updatedAt: new Date(),
      },
    })
    .returning();

  const recipeId = row!.id;

  // Ingredienser + steg: rensa och skriv om (idempotent seed)
  const { eq } = await import("drizzle-orm");
  await db.delete(schema.recipeIngredients).where(eq(schema.recipeIngredients.recipeId, recipeId));
  await db.delete(schema.recipeSteps).where(eq(schema.recipeSteps.recipeId, recipeId));

  await db.insert(schema.recipeIngredients).values(
    recipe.ingredients.map((ri, idx) => ({
      recipeId,
      canonicalIngredientId: ri.ing,
      displayNameSv: ri.nameSv,
      quantity: ri.qty,
      unit: ri.unit,
      note: ri.note ?? null,
      optional: ri.optional ?? false,
      groupName: ri.group ?? null,
      sortOrder: idx,
    })),
  );

  await db.insert(schema.recipeSteps).values(
    recipe.steps.map((step, idx) => ({
      recipeId,
      stepNumber: idx + 1,
      instructionSv: step.text,
      timerSeconds: step.timerSeconds ?? null,
      temperatureC: step.temperatureC ?? null,
      tip: step.tip ?? null,
    })),
  );

  return recipeId;
}

main().catch((err) => {
  console.error("[seed] MISSLYCKADES:", err);
  process.exit(1);
});
