import {
  pgTable,
  text,
  timestamp,
  boolean,
  integer,
  decimal,
  jsonb,
  pgEnum,
  index,
  uniqueIndex,
} from "drizzle-orm/pg-core";
import { relations } from "drizzle-orm";
import { users } from "./users";

export const visibilityEnum = pgEnum("visibility", ["private", "unlisted", "public", "followers"]);
export const difficultyEnum = pgEnum("difficulty", ["easy", "medium", "hard"]);
export const recipeTypeEnum = pgEnum("recipe_type", ["dish", "drink"]);

export type DietaryTags = {
  vegan?: boolean;
  vegetarian?: boolean;
  glutenFree?: boolean;
  dairyFree?: boolean;
  nutFree?: boolean;
  halal?: boolean;
  kosher?: boolean;
};

export const recipes = pgTable("recipes", {
  id: text("id").primaryKey(),
  authorId: text("author_id").notNull().references(() => users.id, { onDelete: "cascade" }),
  title: text("title").notNull(),
  description: text("description"),
  baseServings: integer("base_servings").notNull().default(4),
  recipeType: recipeTypeEnum("recipe_type").notNull().default("dish"),
  visibility: visibilityEnum("visibility").notNull().default("private"),
  sourceUrl: text("source_url"),
  aiGenerated: boolean("ai_generated").notNull().default(false),
  aiModel: text("ai_model"),
  aiPrompt: text("ai_prompt"),
  language: text("language"),
  dietaryTags: jsonb("dietary_tags").$type<DietaryTags>().default({}),
  dietaryVerified: boolean("dietary_verified").notNull().default(false),
  nutritionData: jsonb("nutrition_data").$type<{ perServing: { calories: number; proteinG: number; carbsG: number; fatG: number; fiberG: number; sodiumMg: number } }>(),
  nutritionManual: boolean("nutrition_manual").notNull().default(false),
  difficulty: difficultyEnum("difficulty"),
  prepMins: integer("prep_mins"),
  cookMins: integer("cook_mins"),
  tags: text("tags").array().notNull().default([]),
  isBatchCook: boolean("is_batch_cook").notNull().default(false),
  // User-chosen cover for when there's no photo — null falls back to the
  // deterministic hash-based placeholder (see lib/recipe-placeholder.ts).
  coverIcon: text("cover_icon"),
  coverColor: text("cover_color"),
  createdAt: timestamp("created_at").notNull().defaultNow(),
  updatedAt: timestamp("updated_at").notNull().defaultNow(),
}, (t) => [
  index("recipes_author_idx").on(t.authorId),
  index("recipes_visibility_idx").on(t.visibility),
  index("recipes_dietary_tags_gin").using("gin", t.dietaryTags),
  index("recipes_batch_cook_idx").on(t.isBatchCook),
  index("recipes_type_idx").on(t.recipeType),
]);

export const ingredients = pgTable("ingredients", {
  id: text("id").primaryKey(),
  name: text("name").notNull().unique(),
  aliases: text("aliases").array().notNull().default([]),
  category: text("category"),
  knownAllergens: text("known_allergens").array().notNull().default([]),
  createdAt: timestamp("created_at").notNull().defaultNow(),
});

export const recipeIngredients = pgTable("recipe_ingredients", {
  id: text("id").primaryKey(),
  recipeId: text("recipe_id").notNull().references(() => recipes.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"),
  note: text("note"),
  order: integer("order").notNull().default(0),
}, (t) => [
  index("recipe_ingredients_recipe_idx").on(t.recipeId),
]);

export const recipeSteps = pgTable("recipe_steps", {
  id: text("id").primaryKey(),
  recipeId: text("recipe_id").notNull().references(() => recipes.id, { onDelete: "cascade" }),
  order: integer("order").notNull(),
  instruction: text("instruction").notNull(),
  timerSeconds: integer("timer_seconds"),
  photoUrl: text("photo_url"),
  appliesTo: text("applies_to").array().notNull().default([]),
}, (t) => [
  index("recipe_steps_recipe_idx").on(t.recipeId),
]);

export const recipeBatchDishes = pgTable("recipe_batch_dishes", {
  id: text("id").primaryKey(),
  recipeId: text("recipe_id").notNull().references(() => recipes.id, { onDelete: "cascade" }),
  name: text("name").notNull(),
  description: text("description"),
  order: integer("order").notNull().default(0),
  fridgeDays: integer("fridge_days").notNull(),
  freezerFriendly: boolean("freezer_friendly").notNull().default(false),
  freezerNote: text("freezer_note"),
  dayOfInstructions: text("day_of_instructions").notNull(),
}, (t) => [
  index("recipe_batch_dishes_recipe_idx").on(t.recipeId),
]);

export const recipePhotos = pgTable("recipe_photos", {
  id: text("id").primaryKey(),
  recipeId: text("recipe_id").notNull().references(() => recipes.id, { onDelete: "cascade" }),
  storageKey: text("storage_key").notNull(),
  order: integer("order").notNull().default(0),
  isCover: boolean("is_cover").notNull().default(false),
  sizeMb: integer("size_mb").notNull().default(0),
  createdAt: timestamp("created_at").notNull().defaultNow(),
});

export const recipeNotes = pgTable("recipe_notes", {
  id: text("id").primaryKey(),
  recipeId: text("recipe_id").notNull().references(() => recipes.id, { onDelete: "cascade" }),
  userId: text("user_id").notNull().references(() => users.id, { onDelete: "cascade" }),
  content: text("content").notNull(),
  createdAt: timestamp("created_at").notNull().defaultNow(),
  updatedAt: timestamp("updated_at").notNull().defaultNow(),
}, (t) => [
  uniqueIndex("recipe_notes_recipe_user_idx").on(t.recipeId, t.userId),
]);

export const recipeVariations = pgTable("recipe_variations", {
  id: text("id").primaryKey(),
  parentRecipeId: text("parent_recipe_id").notNull().references(() => recipes.id, { onDelete: "cascade" }),
  childRecipeId: text("child_recipe_id").notNull().references(() => recipes.id, { onDelete: "cascade" }),
  description: text("description"),
  aiGenerated: boolean("ai_generated").notNull().default(false),
  createdAt: timestamp("created_at").notNull().defaultNow(),
});

export const userAllergens = pgTable("user_allergens", {
  userId: text("user_id").notNull().references(() => users.id, { onDelete: "cascade" }),
  allergenTag: text("allergen_tag").notNull(),
});

export const recipesRelations = relations(recipes, ({ one, many }) => ({
  author: one(users, { fields: [recipes.authorId], references: [users.id] }),
  ingredients: many(recipeIngredients),
  steps: many(recipeSteps),
  photos: many(recipePhotos),
  notes: many(recipeNotes),
  childVariations: many(recipeVariations, { relationName: "parent" }),
  parentVariations: many(recipeVariations, { relationName: "child" }),
  batchDishes: many(recipeBatchDishes),
}));

export const recipeBatchDishesRelations = relations(recipeBatchDishes, ({ one }) => ({
  recipe: one(recipes, { fields: [recipeBatchDishes.recipeId], references: [recipes.id] }),
}));

export const recipeIngredientsRelations = relations(recipeIngredients, ({ one }) => ({
  recipe: one(recipes, { fields: [recipeIngredients.recipeId], references: [recipes.id] }),
  ingredient: one(ingredients, { fields: [recipeIngredients.ingredientId], references: [ingredients.id] }),
}));

export const recipePhotosRelations = relations(recipePhotos, ({ one }) => ({
  recipe: one(recipes, { fields: [recipePhotos.recipeId], references: [recipes.id] }),
}));

export const recipeStepsRelations = relations(recipeSteps, ({ one }) => ({
  recipe: one(recipes, { fields: [recipeSteps.recipeId], references: [recipes.id] }),
}));

export const recipeNotesRelations = relations(recipeNotes, ({ one }) => ({
  recipe: one(recipes, { fields: [recipeNotes.recipeId], references: [recipes.id] }),
}));

export const recipeVariationsRelations = relations(recipeVariations, ({ one }) => ({
  parent: one(recipes, { fields: [recipeVariations.parentRecipeId], references: [recipes.id], relationName: "parent" }),
  child: one(recipes, { fields: [recipeVariations.childRecipeId], references: [recipes.id], relationName: "child" }),
}));

export const recipeSnapshots = pgTable("recipe_snapshots", {
  id: text("id").primaryKey(),
  recipeId: text("recipe_id").notNull().references(() => recipes.id, { onDelete: "cascade" }),
  authorId: text("author_id").notNull().references(() => users.id, { onDelete: "cascade" }),
  version: integer("version").notNull(),
  title: text("title").notNull(),
  snapshotData: jsonb("snapshot_data").notNull().$type<{
    title: string;
    description: string | null;
    baseServings: number;
    difficulty: string | null;
    prepMins: number | null;
    cookMins: number | null;
    dietaryTags: Record<string, boolean>;
    ingredients: Array<{ rawName: string; quantity: string | null; unit: string | null; note: string | null; order: number }>;
    steps: Array<{ instruction: string; timerSeconds: number | null; order: number }>;
  }>(),
  createdAt: timestamp("created_at").notNull().defaultNow(),
}, (t) => [
  index("recipe_snapshots_recipe_idx").on(t.recipeId, t.version),
]);

export const recipeSnapshotsRelations = relations(recipeSnapshots, ({ one }) => ({
  recipe: one(recipes, { fields: [recipeSnapshots.recipeId], references: [recipes.id] }),
  author: one(users, { fields: [recipeSnapshots.authorId], references: [users.id] }),
}));
