import { z } from 'zod/v4';
import { NutritionWarning } from '../enums/recipe.enums.js';
import { NutritionInfoSchema } from './product.schemas.js';

const RECIPE_UNIT = ['g', 'ml', 'piece', 'slice'] as const;
const IMPERIAL_UNIT = ['oz', 'lb', 'cup', 'tbsp', 'tsp', 'fl_oz'] as const;

const RecipeUnitSchema = z.enum(RECIPE_UNIT);
const ImperialOrRecipeUnitSchema = z.enum([...RECIPE_UNIT, ...IMPERIAL_UNIT]);

const RecipeIngredientInputSchema = z.object({
  productId: z.string().min(1),
  productName: z.string().min(1).max(200),
  quantity: z.number().positive(),
  unit: ImperialOrRecipeUnitSchema,
  preparation: z.string().max(100).trim().optional(),
  isOptional: z.boolean().default(false),
});

const RecipeStepSchema = z.object({
  order: z.number().int().min(1),
  instruction: z.string().min(1).max(2000).trim(),
  duration: z.number().int().min(1).optional(),
  tip: z.string().max(500).trim().optional(),
});

const RecipeSourceSchema = z.object({
  type: z.enum(['manual', 'url', 'llm_import', 'text_import']),
  url: z.url().optional(),
  importedAt: z.string().datetime().optional(),
});

export const CreateRecipeSchema = z.object({
  name: z.string().min(1).max(200).trim(),
  description: z.string().max(2000).trim().optional(),
  servings: z.number().int().min(1).max(500),
  prepTime: z.number().int().min(0).optional(),
  cookTime: z.number().int().min(0).optional(),
  totalTime: z.number().int().min(0).optional(),
  ingredients: z.array(RecipeIngredientInputSchema).min(1).max(100),
  steps: z.array(RecipeStepSchema).max(100),
  tags: z.array(z.string().min(1).max(50).trim()).max(30).default([]),
  cuisine: z.string().max(100).trim().optional(),
  imageUrl: z.url().optional(),
  source: RecipeSourceSchema.optional(),
  isFavorite: z.boolean().default(false),
});

export const UpdateRecipeSchema = CreateRecipeSchema.partial();

export const ScaleRecipeSchema = z.object({
  targetServings: z.number().int().min(1).max(500),
});

export const ImportRecipeTextSchema = z.object({
  text: z.string().min(1).max(50000),
});

export const ImportRecipeUrlSchema = z.object({
  url: z.url(),
});

export const RecipeQuerySchema = z.object({
  q: z.string().optional(),
  tags: z.string().optional(),
  cuisine: z.string().optional(),
  maxCalories: z.coerce.number().int().min(0).optional(),
  isFavorite: z.coerce.boolean().optional(),
  cursor: z.string().optional(),
  limit: z.coerce.number().int().min(1).max(100).default(20),
});

const StoredRecipeIngredientSchema = z.object({
  productId: z.string(),
  productName: z.string(),
  quantity: z.number(),
  unit: RecipeUnitSchema,
  originalQuantity: z.number().optional(),
  originalUnit: ImperialOrRecipeUnitSchema.optional(),
  preparation: z.string().optional(),
  isOptional: z.boolean(),
  nutritionContribution: NutritionInfoSchema,
});

export const RecipeResponseSchema = z.object({
  _id: z.string(),
  householdId: z.string(),
  name: z.string(),
  description: z.string().optional(),
  servings: z.number(),
  prepTime: z.number().optional(),
  cookTime: z.number().optional(),
  totalTime: z.number().optional(),
  ingredients: z.array(StoredRecipeIngredientSchema),
  steps: z.array(RecipeStepSchema),
  tags: z.array(z.string()),
  cuisine: z.string().optional(),
  imageUrl: z.string().optional(),
  source: RecipeSourceSchema.optional(),
  totalNutrition: NutritionInfoSchema,
  perServingNutrition: NutritionInfoSchema,
  warnings: z.array(z.nativeEnum(NutritionWarning)),
  isFavorite: z.boolean(),
  createdBy: z.string(),
  createdAt: z.string(),
  updatedAt: z.string(),
});

export const RecipeListResponseSchema = z.object({
  data: z.array(RecipeResponseSchema),
  pagination: z.object({
    cursor: z.string().nullable(),
    hasMore: z.boolean(),
    total: z.number().optional(),
  }),
});

export type CreateRecipeInput = z.infer<typeof CreateRecipeSchema>;
export type UpdateRecipeInput = z.infer<typeof UpdateRecipeSchema>;
export type RecipeQueryInput = z.infer<typeof RecipeQuerySchema>;
export type ScaleRecipeInput = z.infer<typeof ScaleRecipeSchema>;
export type ImportRecipeTextInput = z.infer<typeof ImportRecipeTextSchema>;
export type ImportRecipeUrlInput = z.infer<typeof ImportRecipeUrlSchema>;
export type RecipeIngredientInput = z.infer<typeof RecipeIngredientInputSchema>;
