import { describe, expect, it } from "vitest";
import { buildMemoryOverview, deriveMemoryUpdates, renderMemorySummary } from "../src/index.js";
import type { AamosClient, AamosResult } from "@app/ai-contracts";
import type { AamosTaskType } from "@app/ai-contracts";
import type { MemoryItem } from "@app/shared-types";

function makeItem(overrides: Partial<MemoryItem> = {}): MemoryItem {
  return {
    id: "m1",
    userId: "u1",
    kind: "structured_fact",
    key: "favorite_cuisine_swedish",
    summarySv: "Gillar svensk mat",
    value: { favoriteCuisine: "swedish" },
    origin: "user_stated",
    confidence: 1,
    verifiedByUser: true,
    paused: false,
    createdAt: "2026-08-01T00:00:00.000Z",
    updatedAt: "2026-08-01T00:00:00.000Z",
    ...overrides,
  };
}

describe("buildMemoryOverview", () => {
  it("grupperar minnen efter kind", () => {
    const items: MemoryItem[] = [
      makeItem({ id: "a", kind: "structured_fact", summarySv: "Fakta A" }),
      makeItem({ id: "b", kind: "recipe_memory", summarySv: "Recept B" }),
      makeItem({ id: "c", kind: "structured_fact", summarySv: "Fakta C" }),
    ];
    const overview = buildMemoryOverview(items, "sv-SE");
    const kinds = overview.sections.map((s) => s.kind);
    expect(kinds).toContain("structured_fact");
    expect(kinds).toContain("recipe_memory");
    const factSection = overview.sections.find((s) => s.kind === "structured_fact")!;
    expect(factSection.items).toHaveLength(2);
  });

  it("visar origin och confidence tydligt", () => {
    const items: MemoryItem[] = [
      makeItem({ origin: "observed", confidence: 0.75 }),
    ];
    const overview = buildMemoryOverview(items, "sv-SE");
    const item = overview.sections[0]!.items[0]!;
    expect(item.originLabel).toBe("Vi har sett");
    expect(item.confidencePercent).toBe(75);
  });

  it("markerar pausade poster synligt", () => {
    const items: MemoryItem[] = [makeItem({ paused: true })];
    const overview = buildMemoryOverview(items, "sv-SE");
    const item = overview.sections[0]!.items[0]!;
    expect(item.pausedLabel).toBe("Pausad");
    expect(overview.pausedCount).toBe(1);
  });

  it("markerar ai_inferred som gissning", () => {
    const items: MemoryItem[] = [makeItem({ origin: "ai_inferred", confidence: 0.5 })];
    const overview = buildMemoryOverview(items, "sv-SE");
    const item = overview.sections[0]!.items[0]!;
    expect(item.originLabel).toBe("Gissning");
    expect(item.guessLabel).toBe("Detta är en gissning – bekräfta eller ändra om det stämmer.");
  });

  it("sorterar senast uppdaterade överst", () => {
    const items: MemoryItem[] = [
      makeItem({ id: "old", updatedAt: "2026-08-01T00:00:00.000Z" }),
      makeItem({ id: "new", updatedAt: "2026-08-10T00:00:00.000Z" }),
    ];
    const overview = buildMemoryOverview(items, "sv-SE");
    expect(overview.sections[0]!.items[0]!.id).toBe("new");
    expect(overview.sections[0]!.items[1]!.id).toBe("old");
  });

  it("stödjer engelska texter", () => {
    const items: MemoryItem[] = [makeItem({ origin: "user_stated", paused: true })];
    const overview = buildMemoryOverview(items, "en-US");
    const item = overview.sections[0]!.items[0]!;
    expect(item.originLabel).toBe("You said");
    expect(item.pausedLabel).toBe("Paused");
    expect(item.summary).toBe("Favorite cuisine: swedish");
  });

  it("renderMemorySummary stödjer S5-value-former", () => {
    expect(renderMemorySummary({ summarySv: "", value: { favoriteCuisine: "thai" } }, "en-US")).toBe("Favorite cuisine: thai");
    expect(renderMemorySummary({ summarySv: "", value: { avoidIngredientId: "broccoli" } }, "en-US")).toBe("Avoids ingredient: broccoli");
    expect(renderMemorySummary({ summarySv: "", value: { goal: "less_waste" } }, "en-US")).toBe("Goal: less_waste");
    expect(renderMemorySummary({ summarySv: "", value: { primaryGoal: "less_waste" } }, "en-US")).toBe("Primary goal: less_waste");
    expect(renderMemorySummary({ summarySv: "", value: { allergen: "gluten" } }, "en-US")).toBe("Allergy: gluten");
    expect(renderMemorySummary({ summarySv: "", value: { spiceLevelMax: 2 } }, "en-US")).toBe("Max spice level: 2");
  });
});

describe("deriveMemoryUpdates", () => {
  function fakeAamos(output: unknown): AamosClient {
    return {
      async runTask<T extends AamosTaskType>(): Promise<AamosResult<T>> {
        return {
          status: "ok",
          output: output as AamosResult<T>["output"],
          modelVersion: "fake",
          promptVersion: "fake",
          latencyMs: 10,
          costUsd: 0,
          inputTokens: 0,
          outputTokens: 0,
        };
      },
      async healthCheck() {
        return { ok: true };
      },
    };
  }

  it("avvisar fabricerade minnen utan event-stöd", async () => {
    const aamos = fakeAamos({
      memoryUpdates: [
        {
          key: "fabricated",
          kind: "structured_fact",
          summarySv: "Påhittad favoriträtt",
          value: { recipeId: "ghost" },
          origin: "ai_inferred",
          confidence: 0.6,
          expiresAt: null,
          sourceEventIds: ["event-does-not-exist"],
        },
      ],
    });
    const result = await deriveMemoryUpdates(aamos, {
      scope: "user",
      scopeId: "u1",
      events: [{ id: "evt-real", type: "recipe_cooked", occurredAt: "2026-08-01T12:00:00Z", payload: {} }],
      existingMemoryKeys: [],
      consentFlags: { personalization: true, anonymizedImprovement: false, imageTraining: false },
    });
    expect(result.proposals).toHaveLength(0);
  });

  it("behåller grundade minnen med kända event-id", async () => {
    const aamos = fakeAamos({
      memoryUpdates: [
        {
          key: "grounded",
          kind: "structured_fact",
          summarySv: "Ggrundat minne",
          value: { recipeId: "r1" },
          origin: "observed",
          confidence: 0.8,
          expiresAt: null,
          sourceEventIds: ["evt-real"],
        },
      ],
    });
    const result = await deriveMemoryUpdates(aamos, {
      scope: "user",
      scopeId: "u1",
      events: [{ id: "evt-real", type: "recipe_cooked", occurredAt: "2026-08-01T12:00:00Z", payload: {} }],
      existingMemoryKeys: [],
      consentFlags: { personalization: true, anonymizedImprovement: false, imageTraining: false },
    });
    expect(result.proposals).toHaveLength(1);
    expect(result.proposals[0]!.key).toBe("grounded");
  });
});
