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())
}

// --- Enum values (must match pgEnum definitions in pos.ts) ---

export const TransactionType = z.enum([
  'sale',
  'repair_payment',
  'rental_deposit',
  'account_payment',
  'refund',
])
export type TransactionType = z.infer<typeof TransactionType>

export const TransactionStatus = z.enum(['pending', 'completed', 'voided', 'refunded'])
export type TransactionStatus = z.infer<typeof TransactionStatus>

export const PaymentMethod = z.enum([
  'cash',
  'card_present',
  'card_keyed',
  'check',
  'account_charge',
])
export type PaymentMethod = z.infer<typeof PaymentMethod>

export const DiscountType = z.enum(['percent', 'fixed'])
export type DiscountType = z.infer<typeof DiscountType>

export const DiscountAppliesTo = z.enum(['order', 'line_item', 'category'])
export type DiscountAppliesTo = z.infer<typeof DiscountAppliesTo>

export const DrawerStatus = z.enum(['open', 'closed'])
export type DrawerStatus = z.infer<typeof DrawerStatus>

export const TaxCategory = z.enum(['goods', 'service', 'exempt'])
export type TaxCategory = z.infer<typeof TaxCategory>

// --- Transaction schemas ---

export const TransactionCreateSchema = z.object({
  transactionType: TransactionType,
  locationId: opt(z.string().uuid()),
  accountId: opt(z.string().uuid()),
  repairTicketId: opt(z.string().uuid()),
  repairBatchId: opt(z.string().uuid()),
  notes: opt(z.string()),
  taxExempt: z.boolean().default(false),
  taxExemptReason: opt(z.string()),
})
export type TransactionCreateInput = z.infer<typeof TransactionCreateSchema>

export const TransactionLineItemCreateSchema = z.object({
  productId: opt(z.string().uuid()),
  inventoryUnitId: opt(z.string().uuid()),
  description: z.string().min(1).max(255),
  qty: z.number().int().min(1).default(1),
  unitPrice: z.coerce.number().min(0),
})
export type TransactionLineItemCreateInput = z.infer<typeof TransactionLineItemCreateSchema>

export const ApplyDiscountSchema = z.object({
  discountId: opt(z.string().uuid()),
  amount: z.coerce.number().min(0),
  reason: z.string().min(1),
  lineItemId: opt(z.string().uuid()),
})
export type ApplyDiscountInput = z.infer<typeof ApplyDiscountSchema>

export const CompleteTransactionSchema = z.object({
  paymentMethod: PaymentMethod,
  amountTendered: z.coerce.number().min(0).optional(),
  checkNumber: opt(z.string().max(50)),
})
export type CompleteTransactionInput = z.infer<typeof CompleteTransactionSchema>

// --- Discount schemas ---

export const DiscountCreateSchema = z.object({
  name: z.string().min(1).max(255),
  discountType: DiscountType,
  discountValue: z.coerce.number().min(0),
  appliesTo: DiscountAppliesTo.default('line_item'),
  locationId: opt(z.string().uuid()),
  requiresApprovalAbove: z.coerce.number().min(0).optional(),
  isActive: z.boolean().default(true),
  validFrom: opt(z.string()),
  validUntil: opt(z.string()),
})
export type DiscountCreateInput = z.infer<typeof DiscountCreateSchema>

export const DiscountUpdateSchema = DiscountCreateSchema.partial()
export type DiscountUpdateInput = z.infer<typeof DiscountUpdateSchema>

// --- Drawer schemas ---

export const DrawerOpenSchema = z.object({
  locationId: opt(z.string().uuid()),
  registerId: opt(z.string().uuid()),
  openingBalance: z.coerce.number().min(0),
})
export type DrawerOpenInput = z.infer<typeof DrawerOpenSchema>

export const DrawerAdjustmentSchema = z.object({
  type: z.enum(['cash_in', 'cash_out']),
  amount: z.coerce.number().min(0.01),
  reason: z.string().min(1),
})
export type DrawerAdjustmentInput = z.infer<typeof DrawerAdjustmentSchema>

export const DrawerCloseSchema = z.object({
  closingBalance: z.coerce.number().min(0),
  denominations: z
    .record(z.string(), z.number())
    .optional(),
  notes: opt(z.string()),
})
export type DrawerCloseInput = z.infer<typeof DrawerCloseSchema>

// --- Register schemas ---

export const RegisterCreateSchema = z.object({
  locationId: z.string().uuid(),
  name: z.string().min(1).max(100),
})
export type RegisterCreateInput = z.infer<typeof RegisterCreateSchema>

export const RegisterUpdateSchema = z.object({
  name: z.string().min(1).max(100).optional(),
  isActive: z.boolean().optional(),
})
export type RegisterUpdateInput = z.infer<typeof RegisterUpdateSchema>
