import { z } from "zod"

import { specialRequestSchema } from "@/components/HotelReservation/EnterDetails/Details/SpecialRequests/schema"
import { phoneValidator } from "@/utils/zod/phoneValidator"

// stringMatcher regex is copied from current web as specified by requirements.
const stringMatcher =
  /^[A-Za-z¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿ0-9-\s]*$/

const isValidString = (key: string) => stringMatcher.test(key)

export const multiroomErrors = {
  COUNTRY_REQUIRED: "COUNTRY_REQUIRED",
  FIRST_NAME_REQUIRED: "FIRST_NAME_REQUIRED",
  FIRST_NAME_SPECIAL_CHARACTERS: "FIRST_NAME_SPECIAL_CHARACTERS",
  FIRST_AND_LAST_NAME_UNIQUE: "FIRST_AND_LAST_NAME_UNIQUE",
  LAST_NAME_REQUIRED: "LAST_NAME_REQUIRED",
  LAST_NAME_SPECIAL_CHARACTERS: "LAST_NAME_SPECIAL_CHARACTERS",
  PHONE_REQUIRED: "PHONE_REQUIRED",
  PHONE_REQUESTED: "PHONE_REQUESTED",
  EMAIL_REQUIRED: "EMAIL_REQUIRED",
  MEMBERSHIP_NO_ONLY_DIGITS: "MEMBERSHIP_NO_ONLY_DIGITS",
  MEMBERSHIP_NO_INVALID: "MEMBERSHIP_NO_INVALID",
  MEMBERSHIP_NO_UNIQUE: "MEMBERSHIP_NO_UNIQUE",
} as const

export type CrossValidationData = {
  firstName: string
  lastName: string
  membershipNo: string | undefined
}

export function getMultiroomDetailsSchema(
  crossValidationData: CrossValidationData[] | undefined = []
) {
  return z
    .object({
      countryCode: z.string().min(1, multiroomErrors.COUNTRY_REQUIRED),
      email: z.string().email(multiroomErrors.EMAIL_REQUIRED),
      firstName: z
        .string()
        .min(1, multiroomErrors.FIRST_NAME_REQUIRED)
        .refine(isValidString, multiroomErrors.FIRST_NAME_SPECIAL_CHARACTERS),
      join: z.boolean().default(false),
      lastName: z
        .string()
        .min(1, multiroomErrors.LAST_NAME_REQUIRED)
        .refine(isValidString, multiroomErrors.LAST_NAME_SPECIAL_CHARACTERS),
      phoneNumber: phoneValidator(
        multiroomErrors.PHONE_REQUIRED,
        multiroomErrors.PHONE_REQUESTED
      ),
      phoneNumberCC: z.string(),
      membershipNo: z
        .string()
        .optional()
        .refine((val) => {
          if (val) {
            return !val.match(/[^0-9]/g)
          }
          return true
        }, multiroomErrors.MEMBERSHIP_NO_ONLY_DIGITS)
        .refine((num) => {
          if (num) {
            return num.match(/^30812(?!(0|1|2))[0-9]{9}$/)
          }
          return true
        }, multiroomErrors.MEMBERSHIP_NO_INVALID),
      specialRequest: specialRequestSchema,
    })
    .refine(
      (data) =>
        !crossValidationData.some(
          (room) =>
            room.firstName === data.firstName && room.lastName === data.lastName
        ),
      {
        message: multiroomErrors.FIRST_AND_LAST_NAME_UNIQUE,
        path: ["firstName"],
      }
    )
    .refine(
      (data) =>
        !crossValidationData.some(
          (room) =>
            room.firstName === data.firstName && room.lastName === data.lastName
        ),
      {
        message: multiroomErrors.FIRST_AND_LAST_NAME_UNIQUE,
        path: ["lastName"],
      }
    )
    .refine(
      (data) =>
        !crossValidationData.some(
          (room) => room.membershipNo && room.membershipNo === data.membershipNo
        ),
      {
        message: multiroomErrors.MEMBERSHIP_NO_UNIQUE,
        path: ["membershipNo"],
      }
    )
}
