import {
  boolean,
  date,
  doublePrecision,
  index,
  jsonb,
  pgTable,
  text,
  timestamp,
  uuid,
  integer,
} from "drizzle-orm/pg-core";
import type { NutritionDeclaration } from "@app/shared-types";
import {
  createdAt,
  dateKindEnum,
  expiryStatusEnum,
  inventorySourceEnum,
  inventoryTransactionTypeEnum,
  unitEnum,
  updatedAt,
} from "./_shared.js";
import { households, storageLocations } from "./households.js";
import { canonicalIngredients } from "./ingredients.js";
import { products } from "./products.js";
import { users } from "./users.js";

/**
 * Food Twin (spec §8): lagerposter med fullständig spårbarhet.
 * `quantity` är ett cachat saldo – sanningen är inventory_transactions.
 */
export const inventoryItems = pgTable(
  "inventory_items",
  {
    id: uuid("id").primaryKey().defaultRandom(),
    householdId: uuid("household_id")
      .notNull()
      .references(() => households.id, { onDelete: "cascade" }),
    canonicalIngredientId: text("canonical_ingredient_id").references(
      () => canonicalIngredients.id,
    ),
    productId: uuid("product_id").references(() => products.id),
    displayName: text("display_name").notNull(),
    brand: text("brand"),
    quantity: doublePrecision("quantity").notNull().default(0),
    unit: unitEnum("unit").notNull(),
    storageLocationId: uuid("storage_location_id")
      .notNull()
      .references(() => storageLocations.id),
    sublocation: text("sublocation"),
    purchasedAt: date("purchased_at"),
    openedAt: date("opened_at"),
    bestBeforeDate: date("best_before_date"),
    useByDate: date("use_by_date"),
    dateKind: dateKindEnum("date_kind"),
    frozenAt: date("frozen_at"),
    thawedAt: date("thawed_at"),
    priceMinor: integer("price_minor"),
    nutritionPer100: jsonb("nutrition_per_100").$type<NutritionDeclaration>(),
    source: inventorySourceEnum("source").notNull(),
    confidence: doublePrecision("confidence").notNull().default(1),
    verifiedByUser: boolean("verified_by_user").notNull().default(false),
    lastVerifiedAt: timestamp("last_verified_at", { withTimezone: true }),
    expiryStatus: expiryStatusEnum("expiry_status").notNull().default("unknown"),
    /** Sätts när saldot nått 0 och posten arkiverats. */
    depletedAt: timestamp("depleted_at", { withTimezone: true }),
    modelVersion: text("model_version"),
    promptVersion: text("prompt_version"),
    createdAt: createdAt(),
    updatedAt: updatedAt(),
  },
  (t) => [
    index("inventory_items_household_idx").on(t.householdId),
    index("inventory_items_household_bb_idx").on(t.householdId, t.bestBeforeDate),
    index("inventory_items_location_idx").on(t.storageLocationId),
    index("inventory_items_canonical_idx").on(t.canonicalIngredientId),
  ],
);

/** Transaktionsloggen är källan till sanning (spec §8): + inköp, − använt, − kasserat … */
export const inventoryTransactions = pgTable(
  "inventory_transactions",
  {
    id: uuid("id").primaryKey().defaultRandom(),
    householdId: uuid("household_id")
      .notNull()
      .references(() => households.id, { onDelete: "cascade" }),
    inventoryItemId: uuid("inventory_item_id")
      .notNull()
      .references(() => inventoryItems.id, { onDelete: "cascade" }),
    type: inventoryTransactionTypeEnum("type").notNull(),
    quantityDelta: doublePrecision("quantity_delta").notNull(),
    unit: unitEnum("unit").notNull(),
    refType: text("ref_type"),
    refId: uuid("ref_id"),
    actorUserId: uuid("actor_user_id").references(() => users.id, { onDelete: "set null" }),
    note: text("note"),
    /** Värde i SEK för matsvinnsberäkning vid discard (spec §12, §26). */
    valueMinor: integer("value_minor"),
    createdAt: createdAt(),
  },
  (t) => [
    index("inventory_tx_item_idx").on(t.inventoryItemId),
    index("inventory_tx_household_time_idx").on(t.householdId, t.createdAt),
    index("inventory_tx_type_idx").on(t.type),
  ],
);
