import { z } from 'zod'

/** Coerce empty strings to undefined — solves HTML form inputs sending '' for blank optional fields */
function opt<T extends z.ZodTypeAny>(schema: T) {
  return z.preprocess((v) => (v === '' ? undefined : v), schema.optional())
}

export const CategoryCreateSchema = z.object({
  name: z.string().min(1).max(255),
  description: opt(z.string()),
  parentId: opt(z.string().uuid()),
  sortOrder: z.number().int().default(0),
})
export type CategoryCreateInput = z.infer<typeof CategoryCreateSchema>

export const CategoryUpdateSchema = CategoryCreateSchema.partial()
export type CategoryUpdateInput = z.infer<typeof CategoryUpdateSchema>

export const SupplierCreateSchema = z.object({
  name: z.string().min(1).max(255),
  contactName: opt(z.string().max(255)),
  email: opt(z.string().email()),
  phone: opt(z.string().max(50)),
  website: opt(z.string().max(255)),
  accountNumber: opt(z.string().max(100)),
  paymentTerms: opt(z.string().max(100)),
  notes: opt(z.string()),
})
export type SupplierCreateInput = z.infer<typeof SupplierCreateSchema>

export const SupplierUpdateSchema = SupplierCreateSchema.partial()
export type SupplierUpdateInput = z.infer<typeof SupplierUpdateSchema>

// System slugs — used for code-level business logic references.
// Actual valid values are stored in lookup tables and are company-configurable.
export const SystemItemCondition = z.enum(['new', 'excellent', 'good', 'fair', 'poor'])
export const SystemUnitStatus = z.enum([
  'available',
  'sold',
  'rented',
  'on_trial',
  'in_repair',
  'layaway',
  'lost',
  'retired',
])

// API validation accepts any string slug (validated against lookup table at service layer)
export const ItemCondition = z.string().min(1).max(100)
export const UnitStatus = z.string().min(1).max(100)

export const ProductCreateSchema = z.object({
  sku: opt(z.string().max(100)),
  upc: opt(z.string().max(100)),
  name: z.string().min(1).max(255),
  description: opt(z.string()),
  brand: opt(z.string().max(255)),
  model: opt(z.string().max(255)),
  categoryId: opt(z.string().uuid()),
  locationId: opt(z.string().uuid()),
  isSerialized: z.boolean().default(false),
  isRental: z.boolean().default(false),
  isDualUseRepair: z.boolean().default(false),
  isConsumable: z.boolean().default(false),
  price: z.number().min(0).optional(),
  minPrice: z.number().min(0).optional(),
  rentalRateMonthly: z.number().min(0).optional(),
  qtyOnHand: z.number().int().min(0).default(0),
  qtyReorderPoint: z.number().int().min(0).optional(),
})
export type ProductCreateInput = z.infer<typeof ProductCreateSchema>

export const ProductUpdateSchema = ProductCreateSchema.partial()
export type ProductUpdateInput = z.infer<typeof ProductUpdateSchema>

export const ProductSearchSchema = z.object({
  q: z.string().min(1).max(255),
})

export const InventoryUnitCreateSchema = z.object({
  productId: z.string().uuid(),
  locationId: opt(z.string().uuid()),
  serialNumber: opt(z.string().max(255)),
  condition: ItemCondition.default('new'),
  status: UnitStatus.default('available'),
  purchaseDate: opt(z.string().date()),
  purchaseCost: z.number().min(0).optional(),
  notes: opt(z.string()),
})
export type InventoryUnitCreateInput = z.infer<typeof InventoryUnitCreateSchema>

export const InventoryUnitUpdateSchema = InventoryUnitCreateSchema.omit({ productId: true }).partial()
export type InventoryUnitUpdateInput = z.infer<typeof InventoryUnitUpdateSchema>

export const ProductSupplierCreateSchema = z.object({
  supplierId: z.string().uuid(),
  supplierSku: opt(z.string().max(100)),
  isPreferred: z.boolean().default(false),
})
export type ProductSupplierCreateInput = z.infer<typeof ProductSupplierCreateSchema>

export const ProductSupplierUpdateSchema = ProductSupplierCreateSchema.omit({ supplierId: true }).partial()
export type ProductSupplierUpdateInput = z.infer<typeof ProductSupplierUpdateSchema>

export const StockReceiptCreateSchema = z.object({
  supplierId: opt(z.string().uuid()),
  inventoryUnitId: opt(z.string().uuid()),
  qty: z.number().int().min(1).default(1),
  costPerUnit: z.number().min(0),
  receivedDate: z.string().date(),
  invoiceNumber: opt(z.string().max(100)),
  notes: opt(z.string()),
})
export type StockReceiptCreateInput = z.infer<typeof StockReceiptCreateSchema>
