import { TASK_CONTRACTS, type AamosClient } from "@app/ai-contracts";
import type { MemoryItem, MemoryKind, SignalOrigin } from "@app/shared-types";

/**
 * Minnesarkitektur (spec §32):
 *
 * - plattformens databas (memory_items) är den ANVÄNDARSYNLIGA sanningen:
 *   allt som visas i "Vad plattformen vet om mig" och allt som kan korrigeras,
 *   pausas, raderas och exporteras finns där.
 * - AAMOS får härleda nya minnesposter (UPDATE_USER_MEMORY-jobbet), men
 *   förslagen skrivs alltid in i plattformens tabell där användaren äger dem.
 * - Personligt minne är ALDRIG automatiskt träningsdata (spec §32–33);
 *   consentSnapshot följer med varje härledning.
 */

export interface MemoryUpdateProposal {
  key: string;
  kind: MemoryKind;
  summarySv: string;
  value: unknown;
  origin: Exclude<SignalOrigin, "user_stated">;
  confidence: number;
  expiresAt?: string | null;
  /** Händelse-ID:n som stödjer förslaget (R1: grundat, aldrig påhittat). */
  sourceEventIds: string[];
}

export interface MemorySyncInput {
  scope: "user" | "household";
  scopeId: string;
  events: Array<{ id: string; type: string; occurredAt: string; payload: unknown }>;
  existingMemoryKeys: string[];
  consentFlags: {
    personalization: boolean;
    anonymizedImprovement: boolean;
    imageTraining: boolean;
  };
  correlationId?: string;
  localeContext?: import("@app/shared-types").LocaleContext;
}

/**
 * Kör minnesuppdatering via AAMOS. Returnerar granskade förslag + faktisk
 * token/kostnadsanvändning så att workern kan bokföra i ai_usage_counters.
 * Utan personaliseringssamtycke körs ingenting.
 *
 * R1 (grundat, aldrig påhittat): AAMOS får explicit instruktion om att aldrig
 * fabricera minnen; svaret valideras mot Zod-kontraktet.
 */
export async function deriveMemoryUpdates(
  aamos: AamosClient,
  input: MemorySyncInput,
): Promise<{
  proposals: MemoryUpdateProposal[];
  usage: { costUsd: number; inputTokens: number; outputTokens: number } | null;
}> {
  if (!input.consentFlags.personalization) {
    return { proposals: [], usage: null };
  }

  const result = await aamos.runTask(
    "UPDATE_USER_MEMORY",
    {
      scope: input.scope,
      scopeId: input.scopeId,
      events: input.events,
      existingMemoryKeys: input.existingMemoryKeys,
    },
    {
      subjectRef: pseudonymize(input.scopeId),
      consentFlags: input.consentFlags,
      systemInstruction:
        "Du får ENDAST sammanfatta faktiska events. Hitta ALDRIG på minnen, preferenser eller mönster som inte har explicit stöd i events. Varje förslag måste referera till ett eller flera events via sourceEventIds. ai_inferred-förslag ska ha låg konfidens.",
      ...(input.localeContext ? { localeContext: input.localeContext } : {}),
      ...(input.correlationId ? { correlationId: input.correlationId } : {}),
    },
  );

  const usage =
    result.status === "ok" && result.output
      ? {
          costUsd: result.costUsd ?? 0,
          inputTokens: result.inputTokens ?? 0,
          outputTokens: result.outputTokens ?? 0,
        }
      : null;

  if (result.status !== "ok" || !result.output) {
    return { proposals: [], usage };
  }

  // Extra Zod-validering: ett brutet kontrakt ska aldrig nå användardata.
  const parsed = TASK_CONTRACTS["UPDATE_USER_MEMORY"].output.safeParse(result.output);
  if (!parsed.success) {
    // eslint-disable-next-line no-console
    console.error("UPDATE_USER_MEMORY output bröt mot kontraktet:", parsed.error.message);
    return { proposals: [], usage };
  }

  const validEventIds = new Set(input.events.map((e) => e.id));
  const groundedProposals = parsed.data.memoryUpdates.filter((u) => {
    const grounded = u.sourceEventIds.length > 0 && u.sourceEventIds.every((id) => validEventIds.has(id));
    if (!grounded) {
      // eslint-disable-next-line no-console
      console.error(`UPDATE_USER_MEMORY avvisade fabricerat minne: key=${u.key}, sourceEventIds=[${u.sourceEventIds.join(", ")}]`);
    }
    return grounded;
  });

  return {
    proposals: groundedProposals.map((u) => ({
      key: u.key,
      kind: u.kind,
      summarySv: u.summarySv,
      value: u.value,
      origin: u.origin,
      confidence: u.confidence,
      expiresAt: u.expiresAt,
      sourceEventIds: u.sourceEventIds,
    })),
    usage,
  };
}

export interface MemoryOverviewItem extends MemoryItem {
  summary: string;
  /** Lokaliserad etikett för ursprung (user_stated/observed/ai_inferred). */
  originLabel: string;
  /** Konfidens 0–100 %. */
  confidencePercent: number;
  /** Synlig etikett om posten är pausad. */
  pausedLabel?: string;
  /** Tydlig gissningsmarkering för ai_inferred (R1). */
  guessLabel?: string;
}

/** Gruppera minnesposter för "Vad plattformen vet om mig"-vyn. */
export interface MemoryOverview {
  language: string;
  sections: Array<{
    kind: MemoryKind;
    /** Rubrik på begärt språk (i18n M10). titleSv behålls för bakåtkompatibilitet. */
    title: string;
    titleSv: string;
    items: MemoryOverviewItem[];
  }>;
  totalCount: number;
  pausedCount: number;
}

const KIND_TITLES: Record<string, Record<MemoryKind, string>> = {
  sv: {
    structured_fact: "Fakta om dig och hushållet",
    event: "Händelser vi kommer ihåg",
    semantic: "Mönster vi har observerat",
    profile_summary: "Din profil i korthet",
    recipe_memory: "Recept och måltider",
  },
  en: {
    structured_fact: "Facts about you and your household",
    event: "Events we remember",
    semantic: "Patterns we've observed",
    profile_summary: "Your profile at a glance",
    recipe_memory: "Recipes and meals",
  },
  es: {
    structured_fact: "Datos sobre ti y tu hogar",
    event: "Eventos que recordamos",
    semantic: "Patrones observados",
    profile_summary: "Tu perfil de un vistazo",
    recipe_memory: "Recetas y comidas",
  },
  it: {
    structured_fact: "Informazioni su di te e la tua famiglia",
    event: "Eventi che ricordiamo",
    semantic: "Schemi osservati",
    profile_summary: "Il tuo profilo in breve",
    recipe_memory: "Ricette e pasti",
  },
  de: {
    structured_fact: "Fakten über dich und deinen Haushalt",
    event: "Ereignisse, die wir uns merken",
    semantic: "Beobachtete Muster",
    profile_summary: "Dein Profil auf einen Blick",
    recipe_memory: "Rezepte und Mahlzeiten",
  },
  fr: {
    structured_fact: "Infos sur vous et votre foyer",
    event: "Événements mémorisés",
    semantic: "Habitudes observées",
    profile_summary: "Votre profil en un coup d'œil",
    recipe_memory: "Recettes et repas",
  },
  da: {
    structured_fact: "Fakta om dig og husstanden",
    event: "Hændelser vi husker",
    semantic: "Mønstre vi har observeret",
    profile_summary: "Din profil i korte træk",
    recipe_memory: "Opskrifter og måltider",
  },
  nb: {
    structured_fact: "Fakta om deg og husstanden",
    event: "Hendelser vi husker",
    semantic: "Mønstre vi har observert",
    profile_summary: "Profilen din i korte trekk",
    recipe_memory: "Oppskrifter og måltider",
  },
  fi: {
    structured_fact: "Tietoa sinusta ja kotitaloudestasi",
    event: "Muistamamme tapahtumat",
    semantic: "Havaitut tavat",
    profile_summary: "Profiilisi lyhyesti",
    recipe_memory: "Reseptit ja ateriat",
  },
  nl: {
    structured_fact: "Feiten over jou en je huishouden",
    event: "Gebeurtenissen die we onthouden",
    semantic: "Waargenomen patronen",
    profile_summary: "Je profiel in het kort",
    recipe_memory: "Recepten en maaltijden",
  },
  pl: {
    structured_fact: "Fakty o Tobie i Twoim gospodarstwie",
    event: "Zdarzenia, które pamiętamy",
    semantic: "Zaobserwowane wzorce",
    profile_summary: "Twój profil w skrócie",
    recipe_memory: "Przepisy i posiłki",
  },
  pt: {
    structured_fact: "Factos sobre si e o seu agregado",
    event: "Eventos que recordamos",
    semantic: "Padrões observados",
    profile_summary: "O seu perfil em resumo",
    recipe_memory: "Receitas e refeições",
  },
};

const UI_LABELS: Record<
  string,
  {
    origin: Record<SignalOrigin, string>;
    paused: string;
    guess: string;
  }
> = {
  sv: {
    origin: { user_stated: "Du har sagt", observed: "Vi har sett", ai_inferred: "Gissning" },
    paused: "Pausad",
    guess: "Detta är en gissning – bekräfta eller ändra om det stämmer.",
  },
  en: {
    origin: { user_stated: "You said", observed: "We noticed", ai_inferred: "Guess" },
    paused: "Paused",
    guess: "This is a guess — confirm or change it if it fits.",
  },
  es: {
    origin: { user_stated: "Dijiste", observed: "Notamos", ai_inferred: "Suposición" },
    paused: "Pausado",
    guess: "Esto es una suposición: confírmala o cámbiala si encaja.",
  },
  it: {
    origin: { user_stated: "Hai detto", observed: "Abbiamo notato", ai_inferred: "Ipotesi" },
    paused: "In pausa",
    guess: "Questa è un'ipotesi: confermala o modificala se è corretta.",
  },
  de: {
    origin: { user_stated: "Du hast gesagt", observed: "Wir haben bemerkt", ai_inferred: "Vermutung" },
    paused: "Pausiert",
    guess: "Dies ist eine Vermutung: bestätige oder ändere sie, wenn sie stimmt.",
  },
  fr: {
    origin: { user_stated: "Vous avez dit", observed: "Nous avons remarqué", ai_inferred: "Hypothèse" },
    paused: "En pause",
    guess: "Ceci est une hypothèse : confirmez ou modifiez si cela vous convient.",
  },
  da: {
    origin: { user_stated: "Du har sagt", observed: "Vi har set", ai_inferred: "Gæt" },
    paused: "Pauset",
    guess: "Dette er et gæt — bekræft eller ændr det, hvis det passer.",
  },
  nb: {
    origin: { user_stated: "Du har sagt", observed: "Vi har sett", ai_inferred: "Gjettning" },
    paused: "Pauset",
    guess: "Dette er en gjetning — bekreft eller endre hvis det stemmer.",
  },
  fi: {
    origin: { user_stated: "Olet sanonut", observed: "Olemme huomanneet", ai_inferred: "Arvaus" },
    paused: "Tauolla",
    guess: "Tämä on arvaus: vahvista tai muuta se, jos se sopii.",
  },
  nl: {
    origin: { user_stated: "Jij zei", observed: "We hebben gezien", ai_inferred: "Gok" },
    paused: "Gepauzeerd",
    guess: "Dit is een gok: bevestig of pas aan als het klopt.",
  },
  pl: {
    origin: { user_stated: "Powiedziałeś", observed: "Zauważyliśmy", ai_inferred: "Domysł" },
    paused: "Wstrzymane",
    guess: "To jest przypuszczenie — potwierdź lub zmień, jeśli się zgadza.",
  },
  pt: {
    origin: { user_stated: "Disseste", observed: "Reparámos", ai_inferred: "Suposição" },
    paused: "Pausado",
    guess: "Isto é uma suposição: confirma ou altera se fizer sentido.",
  },
};

type MemoryValueRenderer = (value: Record<string, unknown>) => string | null;

const MEMORY_SUMMARY_TEMPLATES: Record<
  string,
  Record<string, MemoryValueRenderer>
> = {
  sv: {
    favoriteCuisine: (v) =>
      typeof v.favoriteCuisine === "string"
        ? `Favoritkök: ${String(v.favoriteCuisine)}`
        : null,
    avoidIngredient: (v) =>
      typeof v.avoidIngredientId === "string"
        ? `Undviker ingrediens: ${String(v.avoidIngredientId)}`
        : null,
    goal: (v) =>
      typeof v.goal === "string" ? `Mål: ${String(v.goal)}` : null,
    primaryGoal: (v) =>
      typeof v.primaryGoal === "string"
        ? `Primärt mål: ${String(v.primaryGoal)}`
        : null,
    allergen: (v) =>
      typeof v.allergen === "string"
        ? `Allergi: ${String(v.allergen)}`
        : null,
    spiceLevelMax: (v) =>
      typeof v.spiceLevelMax === "number"
        ? `Max styrka: ${v.spiceLevelMax}`
        : null,
    dislikedIngredient: (v) =>
      typeof v.dislikedIngredient === "string"
        ? `Undviker: ${String(v.dislikedIngredient)}`
        : null,
    typicalPortions: (v) =>
      typeof v.typicalPortions === "number"
        ? `Laggar vanligen ${v.typicalPortions} portioner`
        : null,
    spicePreference: (v) =>
      typeof v.spicePreference === "string"
        ? `Styrkepreferens: ${String(v.spicePreference)}`
        : null,
  },
  en: {
    favoriteCuisine: (v) =>
      typeof v.favoriteCuisine === "string"
        ? `Favorite cuisine: ${String(v.favoriteCuisine)}`
        : null,
    avoidIngredient: (v) =>
      typeof v.avoidIngredientId === "string"
        ? `Avoids ingredient: ${String(v.avoidIngredientId)}`
        : null,
    goal: (v) =>
      typeof v.goal === "string" ? `Goal: ${String(v.goal)}` : null,
    primaryGoal: (v) =>
      typeof v.primaryGoal === "string"
        ? `Primary goal: ${String(v.primaryGoal)}`
        : null,
    allergen: (v) =>
      typeof v.allergen === "string"
        ? `Allergy: ${String(v.allergen)}`
        : null,
    spiceLevelMax: (v) =>
      typeof v.spiceLevelMax === "number"
        ? `Max spice level: ${v.spiceLevelMax}`
        : null,
    dislikedIngredient: (v) =>
      typeof v.dislikedIngredient === "string"
        ? `Avoids: ${String(v.dislikedIngredient)}`
        : null,
    typicalPortions: (v) =>
      typeof v.typicalPortions === "number"
        ? `Usually cooks ${v.typicalPortions} servings`
        : null,
    spicePreference: (v) =>
      typeof v.spicePreference === "string"
        ? `Spice preference: ${String(v.spicePreference)}`
        : null,
  },
  es: {
    favoriteCuisine: (v) =>
      typeof v.favoriteCuisine === "string"
        ? `Cocina favorita: ${String(v.favoriteCuisine)}`
        : null,
    avoidIngredient: (v) =>
      typeof v.avoidIngredientId === "string"
        ? `Evita ingrediente: ${String(v.avoidIngredientId)}`
        : null,
    goal: (v) =>
      typeof v.goal === "string" ? `Objetivo: ${String(v.goal)}` : null,
    primaryGoal: (v) =>
      typeof v.primaryGoal === "string"
        ? `Objetivo principal: ${String(v.primaryGoal)}`
        : null,
    allergen: (v) =>
      typeof v.allergen === "string"
        ? `Alergia: ${String(v.allergen)}`
        : null,
    spiceLevelMax: (v) =>
      typeof v.spiceLevelMax === "number"
        ? `Nivel máximo de picante: ${v.spiceLevelMax}`
        : null,
    dislikedIngredient: (v) =>
      typeof v.dislikedIngredient === "string"
        ? `Evita: ${String(v.dislikedIngredient)}`
        : null,
    typicalPortions: (v) =>
      typeof v.typicalPortions === "number"
        ? `Suele cocinar ${v.typicalPortions} raciones`
        : null,
    spicePreference: (v) =>
      typeof v.spicePreference === "string"
        ? `Preferencia de picante: ${String(v.spicePreference)}`
        : null,
  },
  it: {
    favoriteCuisine: (v) =>
      typeof v.favoriteCuisine === "string"
        ? `Cucina preferita: ${String(v.favoriteCuisine)}`
        : null,
    avoidIngredient: (v) =>
      typeof v.avoidIngredientId === "string"
        ? `Evita ingrediente: ${String(v.avoidIngredientId)}`
        : null,
    goal: (v) =>
      typeof v.goal === "string" ? `Obiettivo: ${String(v.goal)}` : null,
    primaryGoal: (v) =>
      typeof v.primaryGoal === "string"
        ? `Obiettivo principale: ${String(v.primaryGoal)}`
        : null,
    allergen: (v) =>
      typeof v.allergen === "string"
        ? `Allergia: ${String(v.allergen)}`
        : null,
    spiceLevelMax: (v) =>
      typeof v.spiceLevelMax === "number"
        ? `Livello piccante max: ${v.spiceLevelMax}`
        : null,
    dislikedIngredient: (v) =>
      typeof v.dislikedIngredient === "string"
        ? `Evita: ${String(v.dislikedIngredient)}`
        : null,
    typicalPortions: (v) =>
      typeof v.typicalPortions === "number"
        ? `Di solito cucina ${v.typicalPortions} porzioni`
        : null,
    spicePreference: (v) =>
      typeof v.spicePreference === "string"
        ? `Preferenza piccante: ${String(v.spicePreference)}`
        : null,
  },
  de: {
    favoriteCuisine: (v) =>
      typeof v.favoriteCuisine === "string"
        ? `Lieblingsküche: ${String(v.favoriteCuisine)}`
        : null,
    avoidIngredient: (v) =>
      typeof v.avoidIngredientId === "string"
        ? `Vermeidet Zutat: ${String(v.avoidIngredientId)}`
        : null,
    goal: (v) =>
      typeof v.goal === "string" ? `Ziel: ${String(v.goal)}` : null,
    primaryGoal: (v) =>
      typeof v.primaryGoal === "string"
        ? `Hauptziel: ${String(v.primaryGoal)}`
        : null,
    allergen: (v) =>
      typeof v.allergen === "string"
        ? `Allergie: ${String(v.allergen)}`
        : null,
    spiceLevelMax: (v) =>
      typeof v.spiceLevelMax === "number"
        ? `Max. Schärfe: ${v.spiceLevelMax}`
        : null,
    dislikedIngredient: (v) =>
      typeof v.dislikedIngredient === "string"
        ? `Vermeidet: ${String(v.dislikedIngredient)}`
        : null,
    typicalPortions: (v) =>
      typeof v.typicalPortions === "number"
        ? `Kocht meist ${v.typicalPortions} Portionen`
        : null,
    spicePreference: (v) =>
      typeof v.spicePreference === "string"
        ? `Schärfepräferenz: ${String(v.spicePreference)}`
        : null,
  },
  fr: {
    favoriteCuisine: (v) =>
      typeof v.favoriteCuisine === "string"
        ? `Cuisine préférée: ${String(v.favoriteCuisine)}`
        : null,
    avoidIngredient: (v) =>
      typeof v.avoidIngredientId === "string"
        ? `Évite l'ingrédient: ${String(v.avoidIngredientId)}`
        : null,
    goal: (v) =>
      typeof v.goal === "string" ? `Objectif: ${String(v.goal)}` : null,
    primaryGoal: (v) =>
      typeof v.primaryGoal === "string"
        ? `Objectif principal: ${String(v.primaryGoal)}`
        : null,
    allergen: (v) =>
      typeof v.allergen === "string"
        ? `Allergie: ${String(v.allergen)}`
        : null,
    spiceLevelMax: (v) =>
      typeof v.spiceLevelMax === "number"
        ? `Niveau épicé max: ${v.spiceLevelMax}`
        : null,
    dislikedIngredient: (v) =>
      typeof v.dislikedIngredient === "string"
        ? `Évite: ${String(v.dislikedIngredient)}`
        : null,
    typicalPortions: (v) =>
      typeof v.typicalPortions === "number"
        ? `Cuisine habituellement ${v.typicalPortions} portions`
        : null,
    spicePreference: (v) =>
      typeof v.spicePreference === "string"
        ? `Préférence épicée: ${String(v.spicePreference)}`
        : null,
  },
  da: {
    favoriteCuisine: (v) =>
      typeof v.favoriteCuisine === "string"
        ? `Yndlingskøkken: ${String(v.favoriteCuisine)}`
        : null,
    avoidIngredient: (v) =>
      typeof v.avoidIngredientId === "string"
        ? `Undgår ingrediens: ${String(v.avoidIngredientId)}`
        : null,
    goal: (v) =>
      typeof v.goal === "string" ? `Mål: ${String(v.goal)}` : null,
    primaryGoal: (v) =>
      typeof v.primaryGoal === "string"
        ? `Primært mål: ${String(v.primaryGoal)}`
        : null,
    allergen: (v) =>
      typeof v.allergen === "string"
        ? `Allergi: ${String(v.allergen)}`
        : null,
    spiceLevelMax: (v) =>
      typeof v.spiceLevelMax === "number"
        ? `Max styrke: ${v.spiceLevelMax}`
        : null,
    dislikedIngredient: (v) =>
      typeof v.dislikedIngredient === "string"
        ? `Undgår: ${String(v.dislikedIngredient)}`
        : null,
    typicalPortions: (v) =>
      typeof v.typicalPortions === "number"
        ? `Tilbereder som regel ${v.typicalPortions} portioner`
        : null,
    spicePreference: (v) =>
      typeof v.spicePreference === "string"
        ? `Styrkepræference: ${String(v.spicePreference)}`
        : null,
  },
  nb: {
    favoriteCuisine: (v) =>
      typeof v.favoriteCuisine === "string"
        ? `Favorittkjøkken: ${String(v.favoriteCuisine)}`
        : null,
    avoidIngredient: (v) =>
      typeof v.avoidIngredientId === "string"
        ? `Unngår ingrediens: ${String(v.avoidIngredientId)}`
        : null,
    goal: (v) =>
      typeof v.goal === "string" ? `Mål: ${String(v.goal)}` : null,
    primaryGoal: (v) =>
      typeof v.primaryGoal === "string"
        ? `Primært mål: ${String(v.primaryGoal)}`
        : null,
    allergen: (v) =>
      typeof v.allergen === "string"
        ? `Allergi: ${String(v.allergen)}`
        : null,
    spiceLevelMax: (v) =>
      typeof v.spiceLevelMax === "number"
        ? `Maks styrke: ${v.spiceLevelMax}`
        : null,
    dislikedIngredient: (v) =>
      typeof v.dislikedIngredient === "string"
        ? `Unngår: ${String(v.dislikedIngredient)}`
        : null,
    typicalPortions: (v) =>
      typeof v.typicalPortions === "number"
        ? `Lager vanligvis ${v.typicalPortions} porsjoner`
        : null,
    spicePreference: (v) =>
      typeof v.spicePreference === "string"
        ? `Styrkepreferanse: ${String(v.spicePreference)}`
        : null,
  },
  fi: {
    favoriteCuisine: (v) =>
      typeof v.favoriteCuisine === "string"
        ? `Suosikkikeittiö: ${String(v.favoriteCuisine)}`
        : null,
    avoidIngredient: (v) =>
      typeof v.avoidIngredientId === "string"
        ? `Vältettävä ainesosa: ${String(v.avoidIngredientId)}`
        : null,
    goal: (v) =>
      typeof v.goal === "string" ? `Tavoite: ${String(v.goal)}` : null,
    primaryGoal: (v) =>
      typeof v.primaryGoal === "string"
        ? `Päätavoite: ${String(v.primaryGoal)}`
        : null,
    allergen: (v) =>
      typeof v.allergen === "string"
        ? `Allergia: ${String(v.allergen)}`
        : null,
    spiceLevelMax: (v) =>
      typeof v.spiceLevelMax === "number"
        ? `Max tulisuus: ${v.spiceLevelMax}`
        : null,
    dislikedIngredient: (v) =>
      typeof v.dislikedIngredient === "string"
        ? `Vältää: ${String(v.dislikedIngredient)}`
        : null,
    typicalPortions: (v) =>
      typeof v.typicalPortions === "number"
        ? `Valmistaa yleensä ${v.typicalPortions} annosta`
        : null,
    spicePreference: (v) =>
      typeof v.spicePreference === "string"
        ? `Tulisuusmieltymys: ${String(v.spicePreference)}`
        : null,
  },
  nl: {
    favoriteCuisine: (v) =>
      typeof v.favoriteCuisine === "string"
        ? `Favoriete keuken: ${String(v.favoriteCuisine)}`
        : null,
    avoidIngredient: (v) =>
      typeof v.avoidIngredientId === "string"
        ? `Vermijdt ingrediënt: ${String(v.avoidIngredientId)}`
        : null,
    goal: (v) =>
      typeof v.goal === "string" ? `Doel: ${String(v.goal)}` : null,
    primaryGoal: (v) =>
      typeof v.primaryGoal === "string"
        ? `Primair doel: ${String(v.primaryGoal)}`
        : null,
    allergen: (v) =>
      typeof v.allergen === "string"
        ? `Allergie: ${String(v.allergen)}`
        : null,
    spiceLevelMax: (v) =>
      typeof v.spiceLevelMax === "number"
        ? `Max pittigheid: ${v.spiceLevelMax}`
        : null,
    dislikedIngredient: (v) =>
      typeof v.dislikedIngredient === "string"
        ? `Vermijdt: ${String(v.dislikedIngredient)}`
        : null,
    typicalPortions: (v) =>
      typeof v.typicalPortions === "number"
        ? `Kookt meestal ${v.typicalPortions} porties`
        : null,
    spicePreference: (v) =>
      typeof v.spicePreference === "string"
        ? `Pittigheidspreferentie: ${String(v.spicePreference)}`
        : null,
  },
  pl: {
    favoriteCuisine: (v) =>
      typeof v.favoriteCuisine === "string"
        ? `Ulubiona kuchnia: ${String(v.favoriteCuisine)}`
        : null,
    avoidIngredient: (v) =>
      typeof v.avoidIngredientId === "string"
        ? `Unika składnika: ${String(v.avoidIngredientId)}`
        : null,
    goal: (v) =>
      typeof v.goal === "string" ? `Cel: ${String(v.goal)}` : null,
    primaryGoal: (v) =>
      typeof v.primaryGoal === "string"
        ? `Cel główny: ${String(v.primaryGoal)}`
        : null,
    allergen: (v) =>
      typeof v.allergen === "string"
        ? `Alergia: ${String(v.allergen)}`
        : null,
    spiceLevelMax: (v) =>
      typeof v.spiceLevelMax === "number"
        ? `Maks. ostrość: ${v.spiceLevelMax}`
        : null,
    dislikedIngredient: (v) =>
      typeof v.dislikedIngredient === "string"
        ? `Unika: ${String(v.dislikedIngredient)}`
        : null,
    typicalPortions: (v) =>
      typeof v.typicalPortions === "number"
        ? `Zwykle gotuje ${v.typicalPortions} porcje`
        : null,
    spicePreference: (v) =>
      typeof v.spicePreference === "string"
        ? `Preferencja ostrości: ${String(v.spicePreference)}`
        : null,
  },
  pt: {
    favoriteCuisine: (v) =>
      typeof v.favoriteCuisine === "string"
        ? `Cozinha favorita: ${String(v.favoriteCuisine)}`
        : null,
    avoidIngredient: (v) =>
      typeof v.avoidIngredientId === "string"
        ? `Evita ingrediente: ${String(v.avoidIngredientId)}`
        : null,
    goal: (v) =>
      typeof v.goal === "string" ? `Objetivo: ${String(v.goal)}` : null,
    primaryGoal: (v) =>
      typeof v.primaryGoal === "string"
        ? `Objetivo principal: ${String(v.primaryGoal)}`
        : null,
    allergen: (v) =>
      typeof v.allergen === "string"
        ? `Alergia: ${String(v.allergen)}`
        : null,
    spiceLevelMax: (v) =>
      typeof v.spiceLevelMax === "number"
        ? `Nível picante máx.: ${v.spiceLevelMax}`
        : null,
    dislikedIngredient: (v) =>
      typeof v.dislikedIngredient === "string"
        ? `Evita: ${String(v.dislikedIngredient)}`
        : null,
    typicalPortions: (v) =>
      typeof v.typicalPortions === "number"
        ? `Costuma cozinhar ${v.typicalPortions} porções`
        : null,
    spicePreference: (v) =>
      typeof v.spicePreference === "string"
        ? `Preferência picante: ${String(v.spicePreference)}`
        : null,
  },
};

const SUPPORTED_MEMORY_LANGS = Object.keys(MEMORY_SUMMARY_TEMPLATES);

/**
 * Deterministisk rendering av summary ur strukturerad value (i18n-spec §23, M10).
 * Kända value-former renderas per språk; okända faller tillbaka på summarySv
 * (nya minnen får lokaliserad summary direkt från AAMOS via localeContext).
 */
export function renderMemorySummary(
  item: Pick<MemoryItem, "summarySv" | "value">,
  languageTag: string,
): string {
  const lang = (languageTag.split("-")[0] ?? "sv").toLowerCase();
  const catalog = MEMORY_SUMMARY_TEMPLATES[lang] ?? MEMORY_SUMMARY_TEMPLATES.sv!;
  const v = item.value as Record<string, unknown> | null | undefined;
  if (v && typeof v === "object") {
    if (typeof v.favoriteCuisine === "string" && catalog.favoriteCuisine) {
      const rendered = catalog.favoriteCuisine(v);
      if (rendered) return rendered;
    }
    if (typeof v.avoidIngredientId === "string" && catalog.avoidIngredient) {
      const rendered = catalog.avoidIngredient(v);
      if (rendered) return rendered;
    }
    if (typeof v.goal === "string" && catalog.goal) {
      const rendered = catalog.goal(v);
      if (rendered) return rendered;
    }
    if (typeof v.primaryGoal === "string" && catalog.primaryGoal) {
      const rendered = catalog.primaryGoal(v);
      if (rendered) return rendered;
    }
    if (typeof v.allergen === "string" && catalog.allergen) {
      const rendered = catalog.allergen(v);
      if (rendered) return rendered;
    }
    if (typeof v.spiceLevelMax === "number" && catalog.spiceLevelMax) {
      const rendered = catalog.spiceLevelMax(v);
      if (rendered) return rendered;
    }
    if (typeof v.dislikedIngredient === "string" && catalog.dislikedIngredient) {
      const rendered = catalog.dislikedIngredient(v);
      if (rendered) return rendered;
    }
    if (typeof v.typicalPortions === "number" && catalog.typicalPortions) {
      const rendered = catalog.typicalPortions(v);
      if (rendered) return rendered;
    }
    if (typeof v.spicePreference === "string" && catalog.spicePreference) {
      const rendered = catalog.spicePreference(v);
      if (rendered) return rendered;
    }
  }
  return item.summarySv;
}

/** Språk som stöds av renderMemorySummary. */
export function supportedMemorySummaryLanguages(): string[] {
  return [...SUPPORTED_MEMORY_LANGS];
}

export function buildMemoryOverview(items: MemoryItem[], languageTag = "sv"): MemoryOverview {
  const lang = languageTag.split("-")[0] ?? "sv";
  const titles = KIND_TITLES[lang] ?? KIND_TITLES.sv!;
  const labels = UI_LABELS[lang] ?? UI_LABELS.sv!;
  const byKind = new Map<MemoryKind, MemoryItem[]>();
  for (const item of items) {
    const list = byKind.get(item.kind) ?? [];
    list.push(item);
    byKind.set(item.kind, list);
  }
  const sections = [...byKind.entries()].map(([kind, list]) => ({
    kind,
    title: titles[kind],
    titleSv: KIND_TITLES.sv![kind],
    items: list
      .sort((a, b) => b.updatedAt.localeCompare(a.updatedAt))
      .map((i) => {
        const overviewItem: MemoryOverviewItem = {
          ...i,
          summary: renderMemorySummary(i, languageTag),
          originLabel: labels.origin[i.origin] ?? labels.origin.ai_inferred,
          confidencePercent: Math.round(i.confidence * 100),
        };
        if (i.paused) {
          overviewItem.pausedLabel = labels.paused;
        }
        if (i.origin === "ai_inferred") {
          overviewItem.guessLabel = labels.guess;
        }
        return overviewItem;
      }),
  }));
  return {
    language: lang,
    sections,
    totalCount: items.length,
    pausedCount: items.filter((i) => i.paused).length,
  };
}

/** Pseudonymisera id innan det skickas till AAMOS (spec §56: minimization). */
export function pseudonymize(id: string): string {
  // Enkel stabil pseudonym – riktiga miljöer använder HMAC med rotationsbar nyckel.
  return `subj_${Buffer.from(id).toString("base64url").slice(0, 16)}`;
}
