import { z } from "zod"

import { phoneValidator } from "@/utils/phoneValidator"

export const baseDetailsSchema = z.object({
  countryCode: z.string(),
  email: z.string().email(),
  firstName: z.string(),
  lastName: z.string(),
  phoneNumber: phoneValidator(),
})

export const notJoinDetailsSchema = baseDetailsSchema.merge(
  z.object({
    join: z.literal<boolean>(false),
    zipCode: z.string().optional(),
    dateOfBirth: z.string().optional(),
    termsAccepted: z.boolean().default(false),
    membershipNo: z
      .string()
      .optional()
      .refine((val) => {
        if (val) {
          return !val.match(/[^0-9]/g)
        }
        return true
      }, "Only digits are allowed")
      .refine((num) => {
        if (num) {
          return num.length === 14
        }
        return true
      }, "Membership number needs to be 14 digits"),
  })
)

export const joinDetailsSchema = baseDetailsSchema.merge(
  z.object({
    join: z.literal<boolean>(true),
    zipCode: z.string().min(1, { message: "Zip code is required" }),
    dateOfBirth: z.string().min(1, { message: "Date of birth is required" }),
    termsAccepted: z.literal<boolean>(true, {
      errorMap: (err, ctx) => {
        switch (err.code) {
          case "invalid_literal":
            return { message: "You must accept the terms and conditions" }
        }
        return { message: ctx.defaultError }
      },
    }),
    membershipNo: z.string().optional(),
  })
)

export const guestDetailsSchema = z.discriminatedUnion("join", [
  notJoinDetailsSchema,
  joinDetailsSchema,
])

// For signed in users we accept partial or invalid data. Users cannot
// change their info in this flow, so we don't want to validate it.
export const signedInDetailsSchema = z.object({
  countryCode: z.string().optional(),
  email: z.string().optional(),
  firstName: z.string().optional(),
  lastName: z.string().optional(),
  phoneNumber: z.string().optional(),
})
