import { z } from 'zod/v4';
import { ServingUnit, ProductCategory } from '../enums/product.enums.js';
import { ShoppingListStatus, ShoppingListSourceType } from '../enums/shopping-list.enums.js';

export const ShoppingItemSchema = z.object({
  id: z.string(),
  productId: z.string().optional(),
  customName: z.string().optional(),
  quantity: z.number().positive(),
  unit: z.nativeEnum(ServingUnit),
  checked: z.boolean().default(false),
  checkedAt: z.iso.datetime().optional(),
  checkedBy: z.string().optional(),
  estimatedPrice: z.number().optional(),
  actualPrice: z.number().optional(),
  storeId: z.string().optional(),
  notes: z.string().optional(),
  category: z.nativeEnum(ProductCategory).optional(),
  addedToPantry: z.boolean().default(false),
});

export const CreateShoppingListSchema = z.object({
  name: z.string().min(1).max(100).trim(),
  preferredStoreId: z.string().optional(),
  items: z
    .array(
      z.object({
        productId: z.string().optional(),
        customName: z.string().optional(),
        quantity: z.number().positive(),
        unit: z.nativeEnum(ServingUnit),
        notes: z.string().optional(),
        category: z.nativeEnum(ProductCategory).optional(),
      }),
    )
    .optional()
    .default([]),
});

export const UpdateShoppingListSchema = z.object({
  name: z.string().min(1).max(100).trim().optional(),
  status: z.nativeEnum(ShoppingListStatus).optional(),
  preferredStoreId: z.string().optional(),
  items: z.array(ShoppingItemSchema).optional(),
});

export const AddShoppingItemSchema = z
  .object({
    productId: z.string().optional(),
    customName: z.string().optional(),
    quantity: z.number().positive(),
    unit: z.nativeEnum(ServingUnit),
    notes: z.string().max(500).trim().optional(),
    category: z.nativeEnum(ProductCategory).optional(),
  })
  .refine((data) => data.productId || data.customName, {
    message: 'Must provide either a productId or customName',
  });

export const UpdateShoppingItemSchema = z.object({
  quantity: z.number().positive().optional(),
  unit: z.nativeEnum(ServingUnit).optional(),
  checked: z.boolean().optional(),
  actualPrice: z.number().nonnegative().optional(),
  storeId: z.string().optional(),
  notes: z.string().max(500).trim().optional(),
});

export const ShoppingListResponseSchema = z.object({
  _id: z.string(),
  householdId: z.string(),
  name: z.string(),
  status: z.nativeEnum(ShoppingListStatus),
  items: z.array(ShoppingItemSchema),
  createdFrom: z
    .object({
      type: z.nativeEnum(ShoppingListSourceType),
      referenceId: z.string().optional(),
    })
    .optional(),
  mealPlanId: z.string().optional(),
  totalEstimatedCost: z.number().optional(),
  preferredStoreId: z.string().optional(),
  completedAt: z.string().optional(),
  createdBy: z.string(),
  createdAt: z.string(),
  updatedAt: z.string(),
});

export const ShoppingListListResponseSchema = z.object({
  data: z.array(ShoppingListResponseSchema),
});

export const StoreComparisonResultSchema = z.object({
  singleStoreOptions: z.array(
    z.object({
      storeId: z.string(),
      storeName: z.string(),
      estimatedTotal: z.number(),
      itemsCovered: z.number(),
      itemsMissing: z.array(z.string()),
    }),
  ),
  splitStoreOption: z
    .object({
      stores: z.array(
        z.object({
          storeId: z.string(),
          storeName: z.string(),
          items: z.array(z.string()),
          subtotal: z.number(),
        }),
      ),
      estimatedTotal: z.number(),
      savingsVsBestSingleStore: z.number(),
    })
    .optional(),
});

export const BasketStoreComparisonResponseSchema = StoreComparisonResultSchema;

export const ShoppingListSyncToPantryResponseSchema = z.object({
  addedCount: z.number(),
  pricesLogged: z.number(),
});

export type CreateShoppingListInput = z.infer<typeof CreateShoppingListSchema>;
export type UpdateShoppingListInput = z.infer<typeof UpdateShoppingListSchema>;
export type AddShoppingItemInput = z.infer<typeof AddShoppingItemSchema>;
export type UpdateShoppingItemInput = z.infer<typeof UpdateShoppingItemSchema>;
