import { z } from "zod"

import { nullableNumberValidator } from "@/utils/zod/numberValidator"
import { nullableStringValidator } from "@/utils/zod/stringValidator"

import { CurrencyEnum } from "@/types/enums/currency"
import { RateTypeEnum } from "@/types/enums/rateType"

export const corporateChequeSchema = z
  .object({
    additionalPricePerStay: nullableNumberValidator,
    currency: z.nativeEnum(CurrencyEnum).nullish(),
    numberOfBonusCheques: nullableNumberValidator,
  })
  .transform((data) => ({
    additionalPricePerStay: data.additionalPricePerStay,
    currency: data.currency,
    numberOfCheques: data.numberOfBonusCheques,
  }))

export const redemptionSchema = z.object({
  additionalPricePerStay: nullableNumberValidator,
  currency: z.nativeEnum(CurrencyEnum).nullish(),
  pointsPerNight: nullableNumberValidator,
  pointsPerStay: nullableNumberValidator,
})

export const priceSchema = z.object({
  currency: z.nativeEnum(CurrencyEnum),
  omnibusPricePerNight: nullableNumberValidator,
  pricePerNight: nullableNumberValidator,
  pricePerStay: nullableNumberValidator,
  regularPricePerNight: nullableNumberValidator,
  regularPricePerStay: nullableNumberValidator,
})

const partialPriceSchema = z.object({
  rateCode: nullableStringValidator,
  rateType: z.nativeEnum(RateTypeEnum).catch((err) => {
    const issue = err.error.issues[0]
    // This is necessary to handle cases were a
    // new `rateType` is added in the API that has
    // not yet been handled in web
    if (issue.code === "invalid_enum_value") {
      return issue.received.toString() as RateTypeEnum
    }
    return RateTypeEnum.Regular
  }),
})

export const productTypeCorporateChequeSchema = z
  .object({
    localPrice: corporateChequeSchema,
    requestedPrice: corporateChequeSchema.nullish(),
  })
  .merge(partialPriceSchema)

export const productTypePriceSchema = z
  .object({
    localPrice: priceSchema,
    requestedPrice: priceSchema.nullish(),
  })
  .merge(partialPriceSchema)

export const productTypePointsSchema = z
  .object({
    localPrice: redemptionSchema,
    requestedPrice: redemptionSchema.nullish(),
    hasEnoughPoints: z.boolean().optional().default(false),
  })
  .merge(partialPriceSchema)

export const productTypeVoucherSchema = z
  .object({
    numberOfVouchers: nullableNumberValidator,
  })
  .merge(partialPriceSchema)
