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 BillingMode = z.enum(['consolidated', 'split'])
export type BillingMode = z.infer<typeof BillingMode>

export const PaymentProcessor = z.enum(['stripe', 'global_payments'])
export type PaymentProcessor = z.infer<typeof PaymentProcessor>

export const TaxExemptStatus = z.enum(['none', 'pending', 'approved'])
export type TaxExemptStatus = z.infer<typeof TaxExemptStatus>

export const AccountCreateSchema = z.object({
  name: z.string().min(1).max(255),
  email: opt(z.string().email()),
  phone: opt(z.string().max(50)),
  address: z
    .object({
      street: z.string().optional(),
      city: z.string().optional(),
      state: z.string().optional(),
      zip: z.string().optional(),
    })
    .optional(),
  billingMode: BillingMode.default('consolidated'),
  notes: opt(z.string()),
})
export type AccountCreateInput = z.infer<typeof AccountCreateSchema>

export const AccountUpdateSchema = AccountCreateSchema.partial()
export type AccountUpdateInput = z.infer<typeof AccountUpdateSchema>

export const MemberCreateSchema = z.object({
  accountId: z.string().uuid(),
  firstName: z.string().min(1).max(100),
  lastName: z.string().min(1).max(100),
  dateOfBirth: opt(z.string().date()),
  isMinor: z.boolean().optional(),
  email: opt(z.string().email()),
  phone: opt(z.string().max(50)),
  notes: opt(z.string()),
})
export type MemberCreateInput = z.infer<typeof MemberCreateSchema>

export const MemberUpdateSchema = MemberCreateSchema.omit({ accountId: true }).partial()
export type MemberUpdateInput = z.infer<typeof MemberUpdateSchema>

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

// --- Member Identifier ---

export const IdentifierType = z.enum(['drivers_license', 'passport', 'school_id'])
export type IdentifierType = z.infer<typeof IdentifierType>

export const MemberIdentifierCreateSchema = z.object({
  memberId: z.string().uuid(),
  type: IdentifierType,
  label: opt(z.string().max(100)),
  value: z.string().min(1).max(255),
  issuingAuthority: opt(z.string().max(255)),
  issuedDate: opt(z.string().date()),
  expiresAt: opt(z.string().date()),
  imageFrontFileId: opt(z.string().uuid()),
  imageBackFileId: opt(z.string().uuid()),
  notes: opt(z.string()),
  isPrimary: z.boolean().default(false),
})
export type MemberIdentifierCreateInput = z.infer<typeof MemberIdentifierCreateSchema>

export const MemberIdentifierUpdateSchema = MemberIdentifierCreateSchema.omit({ memberId: true }).partial()
export type MemberIdentifierUpdateInput = z.infer<typeof MemberIdentifierUpdateSchema>

// --- Account Processor Link ---

export const ProcessorLinkCreateSchema = z.object({
  accountId: z.string().uuid(),
  processor: PaymentProcessor,
  processorCustomerId: z.string().min(1).max(255),
})
export type ProcessorLinkCreateInput = z.infer<typeof ProcessorLinkCreateSchema>

export const ProcessorLinkUpdateSchema = z.object({
  isActive: z.boolean().optional(),
})
export type ProcessorLinkUpdateInput = z.infer<typeof ProcessorLinkUpdateSchema>

// --- Account Payment Method ---

export const PaymentMethodCreateSchema = z.object({
  accountId: z.string().uuid(),
  processor: PaymentProcessor,
  processorPaymentMethodId: z.string().min(1).max(255),
  cardBrand: opt(z.string().max(50)),
  lastFour: opt(z.string().length(4)),
  expMonth: z.number().int().min(1).max(12).optional(),
  expYear: z.number().int().min(2000).max(2100).optional(),
  isDefault: z.boolean().default(false),
})
export type PaymentMethodCreateInput = z.infer<typeof PaymentMethodCreateSchema>

export const PaymentMethodUpdateSchema = z.object({
  isDefault: z.boolean().optional(),
  requiresUpdate: z.boolean().optional(),
})
export type PaymentMethodUpdateInput = z.infer<typeof PaymentMethodUpdateSchema>

// --- Tax Exemption ---

export const TaxExemptionCreateSchema = z.object({
  accountId: z.string().uuid(),
  certificateNumber: z.string().min(1).max(255),
  certificateType: opt(z.string().max(100)),
  issuingState: opt(z.string().length(2)),
  expiresAt: opt(z.string().date()),
  notes: opt(z.string()),
})
export type TaxExemptionCreateInput = z.infer<typeof TaxExemptionCreateSchema>

export const TaxExemptionUpdateSchema = z.object({
  certificateNumber: opt(z.string().min(1).max(255)),
  certificateType: opt(z.string().max(100)),
  issuingState: opt(z.string().length(2)),
  expiresAt: opt(z.string().date()),
  notes: opt(z.string()),
})
export type TaxExemptionUpdateInput = z.infer<typeof TaxExemptionUpdateSchema>

// --- Lookup Tables ---

export const LookupCreateSchema = z.object({
  name: z.string().min(1).max(100),
  slug: z.string().min(1).max(100).regex(/^[a-z0-9_]+$/, 'Slug must be lowercase alphanumeric with underscores'),
  description: opt(z.string()),
  sortOrder: z.number().int().default(0),
})
export type LookupCreateInput = z.infer<typeof LookupCreateSchema>

export const LookupUpdateSchema = z.object({
  name: opt(z.string().min(1).max(100)),
  description: opt(z.string()),
  sortOrder: z.number().int().optional(),
  isActive: z.boolean().optional(),
})
export type LookupUpdateInput = z.infer<typeof LookupUpdateSchema>
