import {
  pgTable,
  text,
  timestamp,
  integer,
  boolean,
  date,
  decimal,
  pgEnum,
  index,
  uniqueIndex,
} from "drizzle-orm/pg-core";
import { relations } from "drizzle-orm";
import { users } from "./users";
import { recipes, recipeBatchDishes } from "./recipes";
import { ingredients } from "./recipes";
import { collectionMemberRoleEnum } from "./social";

export const mealTypeEnum = pgEnum("meal_type", ["breakfast", "lunch", "dinner", "snack"]);
export const weekdayEnum = pgEnum("weekday", ["mon", "tue", "wed", "thu", "fri", "sat", "sun"]);

export const mealPlans = pgTable("meal_plans", {
  id: text("id").primaryKey(),
  userId: text("user_id").notNull().references(() => users.id, { onDelete: "cascade" }),
  weekStart: date("week_start").notNull(),
  // Anyone with the link can view (read-only, unlike shopping lists' public
  // link which can also be made editable) — the unguessable id is the sole
  // credential, no separate anonymous-visitor identity.
  isPublic: boolean("is_public").notNull().default(false),
  createdAt: timestamp("created_at").notNull().defaultNow(),
}, (t) => [
  index("meal_plans_user_idx").on(t.userId),
  uniqueIndex("meal_plans_user_week_idx").on(t.userId, t.weekStart),
]);

export const mealPlanEntries = pgTable("meal_plan_entries", {
  id: text("id").primaryKey(),
  mealPlanId: text("meal_plan_id").notNull().references(() => mealPlans.id, { onDelete: "cascade" }),
  day: weekdayEnum("day").notNull(),
  mealType: mealTypeEnum("meal_type").notNull(),
  recipeId: text("recipe_id").references(() => recipes.id, { onDelete: "set null" }),
  batchDishId: text("batch_dish_id").references(() => recipeBatchDishes.id, { onDelete: "set null" }),
  servings: integer("servings").notNull().default(2),
  note: text("note"),
}, (t) => [
  index("meal_plan_entries_plan_idx").on(t.mealPlanId),
  uniqueIndex("meal_plan_entries_plan_day_meal_idx").on(t.mealPlanId, t.day, t.mealType),
]);

export const pantryItems = pgTable("pantry_items", {
  id: text("id").primaryKey(),
  userId: text("user_id").notNull().references(() => users.id, { onDelete: "cascade" }),
  ingredientId: text("ingredient_id").references(() => ingredients.id, { onDelete: "set null" }),
  rawName: text("raw_name").notNull(),
  quantity: decimal("quantity", { precision: 10, scale: 4 }),
  unit: text("unit"),
  notes: text("notes"),
  // Same free-text-or-null category slug as shoppingListItems.aisle — lets
  // the pantry group items the same way the shopping list does. Null means
  // "uncategorized", grouped under an "Other" bucket in the UI, not a
  // migration gap (existing rows are never backfilled).
  aisle: text("aisle"),
  expiresAt: timestamp("expires_at"),
  createdAt: timestamp("created_at").notNull().defaultNow(),
}, (t) => [
  index("pantry_items_user_idx").on(t.userId),
]);

export const shoppingLists = pgTable("shopping_lists", {
  id: text("id").primaryKey(),
  userId: text("user_id").references(() => users.id, { onDelete: "cascade" }),
  name: text("name").notNull(),
  isPublic: boolean("is_public").notNull().default(false),
  // Only meaningful when isPublic is true — lets anyone with the link edit
  // (check/add/reorder) items with no account, like a Google-Docs-style
  // "anyone with the link can edit". The link itself (an unguessable id) is
  // the credential; there's no separate per-visitor identity.
  publicEditable: boolean("public_editable").notNull().default(false),
  generatedAt: timestamp("generated_at"),
  createdAt: timestamp("created_at").notNull().defaultNow(),
});

export const shoppingListItems = pgTable("shopping_list_items", {
  id: text("id").primaryKey(),
  listId: text("list_id").notNull().references(() => shoppingLists.id, { onDelete: "cascade" }),
  ingredientId: text("ingredient_id").references(() => ingredients.id, { onDelete: "set null" }),
  rawName: text("raw_name").notNull(),
  quantity: decimal("quantity", { precision: 10, scale: 4 }),
  unit: text("unit"),
  aisle: text("aisle"),
  checked: boolean("checked").notNull().default(false),
  inPantry: boolean("in_pantry").notNull().default(false),
  sortOrder: integer("sort_order").notNull().default(0),
});

export const shoppingListMembers = pgTable("shopping_list_members", {
  id: text("id").primaryKey(),
  listId: text("list_id").notNull().references(() => shoppingLists.id, { onDelete: "cascade" }),
  userId: text("user_id").notNull().references(() => users.id, { onDelete: "cascade" }),
  role: collectionMemberRoleEnum("role").notNull().default("viewer"),
  createdAt: timestamp("created_at").notNull().defaultNow(),
}, (t) => [
  index("shopping_list_members_list_idx").on(t.listId),
  index("shopping_list_members_user_idx").on(t.userId),
]);

export const mealPlanMembers = pgTable("meal_plan_members", {
  id: text("id").primaryKey(),
  mealPlanId: text("meal_plan_id").notNull().references(() => mealPlans.id, { onDelete: "cascade" }),
  userId: text("user_id").notNull().references(() => users.id, { onDelete: "cascade" }),
  role: collectionMemberRoleEnum("role").notNull().default("viewer"),
  createdAt: timestamp("created_at").notNull().defaultNow(),
}, (t) => [
  index("meal_plan_members_plan_idx").on(t.mealPlanId),
  index("meal_plan_members_user_idx").on(t.userId),
]);

export const mealPlansRelations = relations(mealPlans, ({ one, many }) => ({
  user: one(users, { fields: [mealPlans.userId], references: [users.id] }),
  entries: many(mealPlanEntries),
  members: many(mealPlanMembers),
}));

export const mealPlanEntriesRelations = relations(mealPlanEntries, ({ one }) => ({
  mealPlan: one(mealPlans, { fields: [mealPlanEntries.mealPlanId], references: [mealPlans.id] }),
  recipe: one(recipes, { fields: [mealPlanEntries.recipeId], references: [recipes.id] }),
  batchDish: one(recipeBatchDishes, { fields: [mealPlanEntries.batchDishId], references: [recipeBatchDishes.id] }),
}));

export const mealPlanMembersRelations = relations(mealPlanMembers, ({ one }) => ({
  mealPlan: one(mealPlans, { fields: [mealPlanMembers.mealPlanId], references: [mealPlans.id] }),
  user: one(users, { fields: [mealPlanMembers.userId], references: [users.id] }),
}));

export const shoppingListsRelations = relations(shoppingLists, ({ one, many }) => ({
  user: one(users, { fields: [shoppingLists.userId], references: [users.id] }),
  items: many(shoppingListItems),
  members: many(shoppingListMembers),
}));

export const shoppingListItemsRelations = relations(shoppingListItems, ({ one }) => ({
  list: one(shoppingLists, { fields: [shoppingListItems.listId], references: [shoppingLists.id] }),
}));

export const shoppingListMembersRelations = relations(shoppingListMembers, ({ one }) => ({
  list: one(shoppingLists, { fields: [shoppingListMembers.listId], references: [shoppingLists.id] }),
  user: one(users, { fields: [shoppingListMembers.userId], references: [users.id] }),
}));
