/**
 * Domänentiteter. Speglar databasschemat (packages/database) men i camelCase
 * och utan persistensdetaljer. API:t serialiserar datum som ISO-strängar.
 */
import type {
  ActivityLevel,
  Allergen,
  ConsentKind,
  ConsentStatus,
  CookingMethod,
  CreatorLevel,
  Cuisine,
  DateKind,
  DietPattern,
  Equipment,
  EventType,
  ExpiryStatus,
  FeedbackTag,
  GoalType,
  HouseholdRole,
  InventorySource,
  InventoryTransactionType,
  JobStatus,
  JobType,
  MealLogSource,
  MealType,
  MemoryKind,
  NotificationType,
  PrecisionMode,
  ProfileVisibility,
  RecipeDifficulty,
  RecipeSourceType,
  RecipeStatus,
  RecipeTag,
  RecipeVariantType,
  RecipeVerificationStatus,
  ReligiousRule,
  ScanType,
  Season,
  Sex,
  SignalOrigin,
  StorageLocationType,
  SubscriptionPlan,
  SubscriptionProvider,
  SubscriptionStatus,
  TasteAxis,
  Unit,
  UserRole,
  VerificationStatus,
} from "./enums.js";
import type {
  DailyTargets,
  NutritionDeclaration,
  NutritionProvenance,
  NutritionValues,
} from "./nutrition.js";

// ---------------------------------------------------------------------------
// Gemensamma byggstenar
// ---------------------------------------------------------------------------

/** Spårbarhet för varje AI-härledd datapunkt (spec §9). */
export interface DataProvenance {
  source: InventorySource | "ai" | "system";
  confidence: number;
  verifiedByUser: boolean;
  createdAt: string;
  updatedAt: string;
  lastVerifiedAt?: string;
  modelVersion?: string;
  promptVersion?: string;
}

// ---------------------------------------------------------------------------
// Användare & profil (spec §6) – hälsodata hålls logiskt separerad (spec §7, §56)
// ---------------------------------------------------------------------------

export interface User {
  id: string;
  email: string;
  displayName: string;
  role: UserRole;
  locale: string;
  precisionMode: PrecisionMode;
  onboardingCompleted: boolean;
  createdAt: string;
  updatedAt: string;
}

/** Hälsorelaterad profil – åtkomstskyddad separat från hushållsdata. */
export interface UserHealthProfile {
  userId: string;
  birthYear?: number;
  sex?: Sex;
  heightCm?: number;
  weightKg?: number;
  targetWeightKg?: number;
  activityLevel: ActivityLevel;
  trainingSessionsPerWeek?: number;
  trainingTypes?: string[];
  updatedAt: string;
}

export interface UserPreferences {
  userId: string;
  primaryGoal?: GoalType;
  goals: GoalType[];
  dietPattern: DietPattern;
  religiousRule: ReligiousRule;
  allergens: Allergen[];
  intolerances: string[];
  /** canonical ingredient-id:n som ska undvikas */
  avoidIngredientIds: string[];
  favoriteCuisines: Cuisine[];
  dislikedDishes: string[];
  spiceLevelMax: number;
  weeklyBudgetMinor?: number;
  maxCookingMinutesWeekday?: number;
  equipment: Equipment[];
  defaultPortions: number;
  updatedAt: string;
}

export interface UserConsent {
  userId: string;
  kind: ConsentKind;
  status: ConsentStatus;
  grantedAt?: string;
  revokedAt?: string;
  updatedAt: string;
}

export interface UserDailyTargetsSnapshot {
  userId: string;
  date: string;
  targets: DailyTargets;
  /** Hur målen beräknades – transparens i "Min dag". */
  basis: {
    bmrKcal: number;
    tdeeKcal: number;
    goalAdjustmentKcal: number;
    activityLevel: ActivityLevel;
  };
}

// ---------------------------------------------------------------------------
// Hushåll (spec §7)
// ---------------------------------------------------------------------------

export interface Household {
  id: string;
  name: string;
  inviteCode: string;
  weeklyBudgetMinor?: number;
  /** ISO 4217 – alla belopp i hushållet tolkas i denna valuta (i18n-spec §20). */
  currencyCode: string;
  createdAt: string;
  updatedAt: string;
}

export interface HouseholdMember {
  householdId: string;
  userId: string;
  role: HouseholdRole;
  /** Portionsfaktor för denna person (t.ex. barn 0.6, tränande 1.3). */
  portionFactor: number;
  joinedAt: string;
}

export interface StorageLocation {
  id: string;
  householdId: string;
  type: StorageLocationType;
  name: string;
  /** Underplatser: hyllor, lådor (spec §8). */
  sublocations: string[];
  sortOrder: number;
}

// ---------------------------------------------------------------------------
// Ingredienser & produkter (spec §11)
// ---------------------------------------------------------------------------

export interface CanonicalIngredient {
  id: string; // slug, t.ex. "chicken_breast"
  nameSv: string;
  nameEn: string;
  category: string;
  defaultUnit: Unit;
  /** g per ml, för volym↔massa-konvertering */
  densityGPerMl?: number;
  /** g per styck (t.ex. ett ägg ≈ 58 g) */
  gramsPerPiece?: number;
  allergens: Allergen[];
  /** Diet-flaggor för deterministisk filtrering */
  isVegan: boolean;
  isVegetarian: boolean;
  containsGluten: boolean;
  containsLactose: boolean;
  isPork: boolean;
  isBeef: boolean;
  isAlcohol: boolean;
  nutritionPer100: NutritionDeclaration;
  nutritionProvenance: NutritionProvenance;
  /** Säsonger då råvaran är som bäst (spec §28) */
  peakSeasons: Season[];
  /** Riktvärde för hållbarhet efter öppning/inköp, per förvaringsplats (dagar). Vägledning – ej garanti (spec §13). */
  shelfLifeGuidance?: Partial<Record<StorageLocationType, number>>;
  defaultPriceMinorPerKg?: number;
}

export interface Product {
  id: string;
  gtin?: string;
  name: string;
  brand?: string;
  canonicalIngredientId?: string;
  packageSizeValue?: number;
  packageSizeUnit?: Unit;
  ingredientsText?: string;
  allergens: Allergen[];
  mayContainAllergens: Allergen[];
  nutrition?: NutritionDeclaration;
  imageUrls: string[];
  language: string;
  market: string;
  dataSource: string;
  verificationStatus: VerificationStatus;
  /** Produkter versionshanteras (spec §11, §61.12). */
  version: number;
  validFrom: string;
  validTo?: string;
  createdAt: string;
  updatedAt: string;
}

// ---------------------------------------------------------------------------
// Food Twin – lager (spec §8)
// ---------------------------------------------------------------------------

export interface InventoryItem {
  id: string;
  householdId: string;
  canonicalIngredientId?: string;
  productId?: string;
  displayName: string;
  brand?: string;
  /** Aktuellt saldo (härlett ur transaktioner men cachat för snabb läsning). */
  quantity: number;
  unit: Unit;
  storageLocationId: string;
  sublocation?: string;
  purchasedAt?: string;
  openedAt?: string;
  bestBeforeDate?: string;
  useByDate?: string;
  dateKind?: DateKind;
  frozenAt?: string;
  thawedAt?: string;
  priceMinor?: number;
  nutritionPer100?: NutritionDeclaration;
  source: InventorySource;
  confidence: number;
  verifiedByUser: boolean;
  lastVerifiedAt?: string;
  expiryStatus: ExpiryStatus;
  createdAt: string;
  updatedAt: string;
}

export interface InventoryTransaction {
  id: string;
  householdId: string;
  inventoryItemId: string;
  type: InventoryTransactionType;
  /** Positiv = in, negativ = ut. Samma enhet som posten. */
  quantityDelta: number;
  unit: Unit;
  /** Referens till recept, måltid, kvitto, matlåda etc. */
  refType?: "recipe_cook" | "meal" | "receipt" | "meal_box" | "shopping" | "scan" | "manual";
  refId?: string;
  actorUserId?: string;
  note?: string;
  createdAt: string;
}

// ---------------------------------------------------------------------------
// Recept (spec §14–16)
// ---------------------------------------------------------------------------

/** Maskinläsbart Recipe DNA (spec §16). */
export interface RecipeDNA {
  cuisine: Cuisine;
  protein?: string;
  carbohydrate?: string;
  vegetables: string[];
  flavorProfile: string[];
  spiceLevel: number;
  method: CookingMethod;
  timeMinutes: number;
  calories: number;
  proteinGrams: number;
}

export interface RecipeIngredient {
  id: string;
  recipeId: string;
  canonicalIngredientId: string;
  displayNameSv: string;
  quantity: number;
  unit: Unit;
  note?: string;
  optional: boolean;
  /** Gruppering, t.ex. "Sås", "Topping" */
  groupName?: string;
  sortOrder: number;
}

export interface RecipeStep {
  id: string;
  recipeId: string;
  stepNumber: number;
  instructionSv: string;
  /** Timer i sekunder om steget har en naturlig timer (Cooking Mode, spec §41). */
  timerSeconds?: number;
  temperatureC?: number;
  tip?: string;
}

export interface Recipe {
  id: string;
  slug: string;
  titleSv: string;
  descriptionSv: string;
  country?: string;
  region?: string;
  cuisine: Cuisine;
  mealTypes: MealType[];
  tags: RecipeTag[];
  methods: CookingMethod[];
  equipment: Equipment[];
  difficulty: RecipeDifficulty;
  prepTimeMinutes: number;
  cookTimeMinutes: number;
  totalTimeMinutes: number;
  portions: number;
  /** Deterministiskt beräknad av nutrition-engine utifrån ingredienser (spec §61.1). */
  nutritionPerPortion: NutritionValues;
  allergens: Allergen[];
  spiceLevel: number;
  estimatedCostMinorPerPortion?: number;
  storageGuidanceSv?: string;
  mealPrepFriendly: boolean;
  freezerFriendly: boolean;
  peakSeasons: Season[];
  holidayTags: string[];
  dna: RecipeDNA;
  variantType: RecipeVariantType;
  /** Länk till grundreceptet om detta är en variant (spec §16). */
  variantOfRecipeId?: string;
  /** Fork-ursprung (spec §35): "Baserat på recept av X". */
  forkedFromRecipeId?: string;
  status: RecipeStatus;
  verificationStatus: RecipeVerificationStatus;
  sourceType: RecipeSourceType;
  sourceRegistryId?: string;
  creatorUserId?: string;
  creatorDisplayName?: string;
  imageUrls: string[];
  version: number;
  ratingAverage?: number;
  ratingCount: number;
  cookCount: number;
  favoriteCount: number;
  createdAt: string;
  updatedAt: string;
}

export interface RecipeRating {
  id: string;
  recipeId: string;
  userId: string;
  stars: number;
  feedbackTags: FeedbackTag[];
  comment?: string;
  createdAt: string;
}

export interface Substitution {
  id: string;
  fromIngredientId: string;
  toIngredientId: string;
  ratio: number;
  instructionsSv?: string;
  bestFor: string[];
  notRecommendedFor: string[];
  flavorImpactSv?: string;
  textureImpactSv?: string;
}

/** Source registry för juridisk spårbarhet (spec §15). */
export interface RecipeSourceRegistryEntry {
  id: string;
  sourceName: string;
  license: string;
  rightToStore: boolean;
  rightToModify: boolean;
  rightToDisplay: boolean;
  attributionRequired: boolean;
  attributionText?: string;
  commercialUse: boolean;
  validFrom: string;
  validTo?: string;
  notes?: string;
}

// ---------------------------------------------------------------------------
// Måltider, matlådor (spec §22–24)
// ---------------------------------------------------------------------------

export interface Meal {
  id: string;
  userId: string;
  householdId?: string;
  date: string; // YYYY-MM-DD
  mealType: MealType;
  source: MealLogSource;
  recipeId?: string;
  titleSv: string;
  portionFraction: number;
  nutrition: NutritionValues;
  nutritionIsEstimate: boolean;
  estimateRangeKcal?: { min: number; max: number };
  photoUrl?: string;
  scanJobId?: string;
  loggedAt: string;
}

export interface MealBox {
  id: string;
  householdId: string;
  recipeId?: string;
  titleSv: string;
  portions: number;
  portionsRemaining: number;
  kcalPerPortion?: number;
  nutritionPerPortion?: NutritionValues;
  cookedAt: string;
  storageLocationId: string;
  frozen: boolean;
  /** Rekommenderad senaste användning (vägledning, ej garanti – spec §13). */
  recommendedUseBy: string;
  reservedForUserId?: string;
  status: "available" | "reserved" | "consumed" | "discarded";
  createdAt: string;
}

// ---------------------------------------------------------------------------
// Planering, inköp, budget (spec §25–27)
// ---------------------------------------------------------------------------

export interface WeekPlan {
  id: string;
  householdId: string;
  /** Måndag i ISO-vecka, YYYY-MM-DD */
  weekStartDate: string;
  status: "draft" | "active" | "completed";
  generatedBy: "user" | "engine";
  notes?: string;
  createdAt: string;
  updatedAt: string;
}

export interface WeekPlanEntry {
  id: string;
  weekPlanId: string;
  date: string;
  mealType: MealType;
  recipeId?: string;
  mealBoxId?: string;
  titleSv: string;
  portions: number;
  status: "planned" | "cooked" | "skipped" | "moved";
  /** Förklaring vid dynamisk omplanering (spec §25). */
  rescheduleReasonSv?: string;
  sortOrder: number;
}

export interface ShoppingList {
  id: string;
  householdId: string;
  name: string;
  status: "active" | "completed" | "archived";
  weekPlanId?: string;
  createdAt: string;
  updatedAt: string;
}

export interface ShoppingListItem {
  id: string;
  shoppingListId: string;
  canonicalIngredientId?: string;
  displayName: string;
  quantity: number;
  unit: Unit;
  /** Butiksavdelning för sortering (spec §27). */
  storeSection: string;
  suggestedPackageSize?: string;
  estimatedPriceMinor?: number;
  checked: boolean;
  addedByUserId?: string;
  /** Härledd från recept/plan eller manuellt tillagd. */
  origin: "plan" | "recipe" | "manual" | "forecast" | "restock";
  sortOrder: number;
}

export interface Receipt {
  id: string;
  householdId: string;
  storeName?: string;
  purchaseDate?: string;
  totalMinor?: number;
  discountMinor?: number;
  imageUrl?: string;
  scanJobId?: string;
  status: "pending" | "confirmed" | "rejected";
  createdAt: string;
}

export interface ReceiptLine {
  id: string;
  receiptId: string;
  rawText: string;
  normalizedName?: string;
  canonicalIngredientId?: string;
  productId?: string;
  quantity?: number;
  unit?: Unit;
  unitPriceMinor?: number;
  totalPriceMinor?: number;
  confidence: number;
  verifiedByUser: boolean;
  addedToInventory: boolean;
}

// ---------------------------------------------------------------------------
// Skanningsjobb (spec §50, §54)
// ---------------------------------------------------------------------------

export interface ScanJob {
  id: string;
  userId: string;
  householdId?: string;
  scanType: ScanType;
  jobType: JobType;
  status: JobStatus;
  s3Keys: string[];
  /** Strukturerat AI-resultat, validerat mot ai-contracts. */
  result?: unknown;
  error?: string;
  modelVersion?: string;
  promptVersion?: string;
  latencyMs?: number;
  costUsd?: number;
  createdAt: string;
  updatedAt: string;
  completedAt?: string;
}

// ---------------------------------------------------------------------------
// Minne (spec §32)
// ---------------------------------------------------------------------------

export interface MemoryItem {
  id: string;
  userId?: string;
  householdId?: string;
  kind: MemoryKind;
  key: string;
  /** Läsbar sammanfattning som visas i "Vad plattformen vet om mig". */
  summarySv: string;
  value: unknown;
  origin: SignalOrigin;
  confidence: number;
  verifiedByUser: boolean;
  paused: boolean;
  createdAt: string;
  updatedAt: string;
  lastUsedAt?: string;
  expiresAt?: string;
}

export interface TasteSignal {
  id: string;
  userId: string;
  axis: TasteAxis;
  /** -1 (mindre) … +1 (mer) */
  direction: number;
  strength: number;
  origin: SignalOrigin;
  refRecipeId?: string;
  createdAt: string;
}

// ---------------------------------------------------------------------------
// Säsong & event (spec §28)
// ---------------------------------------------------------------------------

export interface SeasonEvent {
  id: string;
  slug: string;
  nameSv: string;
  market: string;
  /** Datumregel: fast datum (MM-DD), beräknad (t.ex. midsommar) eller intervall. */
  dateRule:
    | { kind: "fixed"; monthDay: string }
    | { kind: "range"; startMonthDay: string; endMonthDay: string }
    | { kind: "computed"; algorithm: "midsummer" | "easter" | "advent" | "custom" };
  /** Hur många dagar före eventet det ska börja påverka rekommendationer. */
  leadDays: number;
  foodTags: string[];
  recipeSlugs: string[];
  priority: number;
  active: boolean;
}

// ---------------------------------------------------------------------------
// Prenumerationer & entitlements (spec §45–47)
// ---------------------------------------------------------------------------

export interface Subscription {
  id: string;
  userId: string;
  householdId?: string;
  provider: SubscriptionProvider;
  productId: string;
  plan: SubscriptionPlan;
  originalTransactionId?: string;
  status: SubscriptionStatus;
  purchasedAt?: string;
  expiresAt?: string;
  gracePeriodExpiresAt?: string;
  canceledAt?: string;
  lastVerifiedAt?: string;
  createdAt: string;
  updatedAt: string;
}

export interface Entitlements {
  plan: SubscriptionPlan;
  status: SubscriptionStatus | "free";
  maxHouseholdMembers: number;
  aiScansPerMonth: number;
  aiScansUsedThisMonth: number;
  weekPlanning: boolean;
  advancedNutrition: boolean;
  communityPublish: boolean;
  expiresAt?: string;
  graceUntil?: string;
  /** Signerad token för offline-verifiering med begränsad giltighet (spec §44). */
  signedToken?: string;
}

// ---------------------------------------------------------------------------
// Events, flags, audit (spec §55–57)
// ---------------------------------------------------------------------------

export interface DomainEvent<TPayload = unknown> {
  id: string;
  type: EventType;
  occurredAt: string;
  userId?: string;
  householdId?: string;
  payload: TPayload;
  correlationId?: string;
}

export interface FeatureFlag {
  key: string;
  enabled: boolean;
  descriptionSv?: string;
  /** Procent av användare (0–100) vid gradvis utrullning. */
  rolloutPercent: number;
  updatedAt: string;
}

export interface AuditLogEntry {
  id: string;
  actorUserId?: string;
  actorType: "user" | "admin" | "system" | "worker";
  action: string;
  targetType?: string;
  targetId?: string;
  metadata?: Record<string, unknown>;
  ip?: string;
  correlationId?: string;
  createdAt: string;
}

export interface AppNotification {
  id: string;
  userId: string;
  type: NotificationType;
  titleSv: string;
  bodySv: string;
  data?: Record<string, unknown>;
  scheduledFor?: string;
  sentAt?: string;
  readAt?: string;
  createdAt: string;
}

// ---------------------------------------------------------------------------
// Creator (spec §37)
// ---------------------------------------------------------------------------

export interface CreatorStats {
  userId: string;
  displayName: string;
  visibility: ProfileVisibility;
  level: CreatorLevel;
  publishedRecipes: number;
  followers: number;
  totalCooks: number;
  totalFavorites: number;
  averageRating?: number;
  verifiedRecipes: number;
  badges: string[];
  updatedAt: string;
}
