import type { Database } from "@app/database";
import { schema } from "@app/database";
import type { Allergen, Cuisine, GoalType } from "@app/shared-types";

/**
 * Spegla onboarding-angivna preferenser i användarens synliga minne och
 * smaksignaler (S5). Allt skrivs som `user_stated` / `verifiedByUser=true`.
 *
 * - memory_items: upsert på (userId, key).
 * - taste_signals: upsert på (userId, axis, target).
 *
 * Idempotent – upprepade anrop skapar inga dubletter.
 */
const ONBOARDING_ORIGIN = "user_stated" as const;
const ONBOARDING_CONFIDENCE = 1;
const TASTE_STRENGTH = 0.9;

export interface OnboardingMemoryInput {
  primaryGoal?: GoalType | null;
  goals?: GoalType[];
  allergens?: Allergen[];
  favoriteCuisines?: Cuisine[];
  avoidIngredientIds?: string[];
  spiceLevelMax?: number | null;
}

interface MemoryEntry {
  key: string;
  summarySv: string;
  value: unknown;
}

export async function syncOnboardingMemory(
  db: Database,
  userId: string,
  prefs: OnboardingMemoryInput,
): Promise<void> {
  const memoryEntries: MemoryEntry[] = [];

  if (prefs.primaryGoal) {
    memoryEntries.push({
      key: `goal:primary:${prefs.primaryGoal}`,
      summarySv: `Primärt mål: ${prefs.primaryGoal}`,
      value: { primaryGoal: prefs.primaryGoal },
    });
  }

  for (const goal of prefs.goals ?? []) {
    memoryEntries.push({
      key: `goal:${goal}`,
      summarySv: `Mål: ${goal}`,
      value: { goal },
    });
  }

  for (const allergen of prefs.allergens ?? []) {
    memoryEntries.push({
      key: `allergen:${allergen}`,
      summarySv: `Allergi: ${allergen}`,
      value: { allergen },
    });
  }

  for (const cuisine of prefs.favoriteCuisines ?? []) {
    memoryEntries.push({
      key: `favorite-cuisine:${cuisine}`,
      summarySv: `Favoritkök: ${cuisine}`,
      value: { favoriteCuisine: cuisine },
    });
  }

  for (const ingredientId of prefs.avoidIngredientIds ?? []) {
    memoryEntries.push({
      key: `avoid-ingredient:${ingredientId}`,
      summarySv: `Undviker ingrediens: ${ingredientId}`,
      value: { avoidIngredientId: ingredientId },
    });
  }

  if (prefs.spiceLevelMax != null) {
    memoryEntries.push({
      key: "spice-level-max",
      summarySv: `Max styrka: ${prefs.spiceLevelMax}`,
      value: { spiceLevelMax: prefs.spiceLevelMax },
    });
  }

  for (const entry of memoryEntries) {
    await db
      .insert(schema.memoryItems)
      .values({
        userId,
        kind: "structured_fact",
        key: entry.key,
        summarySv: entry.summarySv,
        value: entry.value,
        origin: ONBOARDING_ORIGIN,
        confidence: ONBOARDING_CONFIDENCE,
        verifiedByUser: true,
      })
      .onConflictDoUpdate({
        target: [schema.memoryItems.userId, schema.memoryItems.key],
        set: {
          summarySv: entry.summarySv,
          value: entry.value,
          origin: ONBOARDING_ORIGIN,
          confidence: ONBOARDING_CONFIDENCE,
          verifiedByUser: true,
          updatedAt: new Date(),
        },
      });
  }

  const tasteEntries: Array<{
    axis: "cuisine" | "ingredient_avoid";
    target: string;
    direction: number;
  }> = [];

  for (const cuisine of prefs.favoriteCuisines ?? []) {
    tasteEntries.push({ axis: "cuisine", target: cuisine, direction: 1 });
  }

  for (const ingredientId of prefs.avoidIngredientIds ?? []) {
    tasteEntries.push({
      axis: "ingredient_avoid",
      target: ingredientId,
      direction: -1,
    });
  }

  for (const signal of tasteEntries) {
    await db
      .insert(schema.tasteSignals)
      .values({
        userId,
        axis: signal.axis,
        target: signal.target,
        direction: signal.direction,
        strength: TASTE_STRENGTH,
        origin: ONBOARDING_ORIGIN,
      })
      .onConflictDoUpdate({
        target: [
          schema.tasteSignals.userId,
          schema.tasteSignals.axis,
          schema.tasteSignals.target,
        ],
        set: {
          direction: signal.direction,
          strength: TASTE_STRENGTH,
          origin: ONBOARDING_ORIGIN,
        },
      });
  }
}
