import { z } from "zod"

import {
  productTypeCorporateChequeSchema,
  productTypePointsSchema,
  productTypePriceSchema,
  productTypeVoucherSchema,
} from "../productTypePrice"
import { rateDefinitionSchema } from "./rateDefinition"

import { RateEnum } from "@/types/enums/rate"

const baseProductSchema = z.object({
  // transform empty string to undefined
  bookingCode: z
    .string()
    .optional()
    .transform((val) => val),
  // Used to set the rate that we use to chose titles etc.
  rate: z.nativeEnum(RateEnum).default(RateEnum.save),
  rateDefinition: rateDefinitionSchema.optional().transform((val) =>
    val
      ? val
      : {
          breakfastIncluded: false,
          cancellationRule: "",
          cancellationText: "",
          displayPriceRed: false,
          isCampaignRate: false,
          isMemberRate: false,
          isPackageRate: false,
          generalTerms: [],
          mustBeGuaranteed: false,
          rateCode: "",
          rateType: "",
          title: "",
        }
  ),
  rateDefinitionMember: rateDefinitionSchema.optional(),
})

function mapBaseProduct(baseProduct: typeof baseProductSchema._type) {
  return {
    bookingCode: baseProduct.bookingCode,
    rate: baseProduct.rate,
    rateDefinition: baseProduct.rateDefinition,
    rateDefinitionMember: baseProduct.rateDefinitionMember,
  }
}

export const corporateChequeProduct = z
  .object({
    productType: z
      .object({
        bonusCheque: productTypeCorporateChequeSchema,
      })
      .transform((data) => ({
        corporateCheque: data.bonusCheque,
      })),
  })
  .merge(baseProductSchema)
  .transform((data) => ({
    ...data.productType,
    ...mapBaseProduct(data),
  }))

export const priceProduct = z
  .object({
    productType: z.object({
      member: productTypePriceSchema.nullish().default(null),
      public: productTypePriceSchema.nullish().default(null),
    }),
  })
  .merge(baseProductSchema)
  .transform((data) => ({
    ...data.productType,
    ...mapBaseProduct(data),
  }))

export const redemptionProduct = z
  .object({
    redemption: productTypePointsSchema,
  })
  .merge(baseProductSchema)
  .transform((data) => ({
    redemption: data.redemption,
    ...mapBaseProduct(data),
  }))

export const redemptionsProduct = z
  .object({
    productType: z.object({
      redemptions: z
        .array(productTypePointsSchema.merge(baseProductSchema))
        .transform((data) =>
          data.map(
            ({
              bookingCode,
              rate,
              rateDefinition,
              rateDefinitionMember,
              ...redemption
            }) => ({
              bookingCode,
              rate,
              rateDefinition,
              rateDefinitionMember,
              redemption,
            })
          )
        ),
    }),
  })
  .transform((data) => data.productType.redemptions)

export const voucherProduct = z
  .object({
    productType: z.object({
      voucher: productTypeVoucherSchema,
    }),
  })
  .merge(baseProductSchema)
  .transform((data) => ({
    ...data.productType,
    ...mapBaseProduct(data),
  }))

export const productSchema = z.union([
  corporateChequeProduct,
  redemptionsProduct,
  voucherProduct,
  priceProduct,
])
