import { z } from "zod"

import { discriminatedUnionArray } from "@/lib/discriminatedUnion"

import { removeMultipleSlashes } from "@/utils/url"

import {
  activitiesCardRefSchema,
  activitiesCardSchema,
} from "../schemas/blocks/activitiesCard"
import { hotelFaqRefsSchema, hotelFaqSchema } from "../schemas/blocks/hotelFaq"
import { spaPageRefSchema, spaPageSchema } from "../schemas/blocks/spaPage"
import { systemSchema } from "../schemas/system"

import { HotelPageEnum } from "@/types/enums/hotelPage"
import type {
  ActivitiesCard,
  SpaPage,
} from "@/types/trpc/routers/contentstack/hotelPage"

const contentBlockActivities = z
  .object({
    __typename: z.literal(HotelPageEnum.ContentStack.blocks.ActivitiesCard),
  })
  .merge(activitiesCardSchema)

const contentBlockSpaPage = z
  .object({
    __typename: z.literal(HotelPageEnum.ContentStack.blocks.SpaPage),
  })
  .merge(spaPageSchema)

export const contentBlock = z.discriminatedUnion("__typename", [
  contentBlockActivities,
  contentBlockSpaPage,
])

export const hotelPageSchema = z.object({
  hotel_page: z
    .object({
      hotel_navigation: z
        .object({
          overview: z.string().nullish(),
          rooms: z.string().nullish(),
          restaurant_bar: z.string().nullish(),
          conferences_meetings: z.string().nullish(),
          health_wellness: z.string().nullish(),
          activities: z.string().nullish(),
          offers: z.string().nullish(),
          faq: z.string().nullish(),
        })
        .nullish(),
      content: discriminatedUnionArray(contentBlock.options)
        .nullable()
        .transform((data) => {
          let spaPage: SpaPage | undefined
          let activitiesCards: ActivitiesCard[] = []

          data?.map((block) => {
            switch (block.typename) {
              case HotelPageEnum.ContentStack.blocks.ActivitiesCard:
                activitiesCards.push(block)
                break
              case HotelPageEnum.ContentStack.blocks.SpaPage:
                spaPage = block
                break
              default:
                break
            }
          })
          return { spaPage, activitiesCards }
        }),
      faq: hotelFaqSchema.nullable(),
      hotel_page_id: z.string(),
      title: z.string(),
      url: z.string(),
      system: systemSchema.merge(
        z.object({
          created_at: z.string(),
          updated_at: z.string(),
        })
      ),
    })
    .transform(({ hotel_navigation, ...rest }) => ({
      sectionHeadings: hotel_navigation,
      ...rest,
    })),
})

/** REFS */
const hotelPageActivitiesCardRefs = z
  .object({
    __typename: z.literal(HotelPageEnum.ContentStack.blocks.ActivitiesCard),
  })
  .merge(activitiesCardRefSchema)

const hotelPageSpaPageRefs = z
  .object({
    __typename: z.literal(HotelPageEnum.ContentStack.blocks.SpaPage),
  })
  .merge(spaPageRefSchema)

const hotelPageBlockRefsItem = z.discriminatedUnion("__typename", [
  hotelPageActivitiesCardRefs,
  hotelPageSpaPageRefs,
])

export const hotelPageRefsSchema = z.object({
  hotel_page: z.object({
    content: discriminatedUnionArray(hotelPageBlockRefsItem.options).nullable(),
    faq: hotelFaqRefsSchema.nullable(),
    system: systemSchema,
  }),
  trackingProps: z.object({
    url: z.string(),
  }),
})

export const hotelPageUrlsSchema = z
  .object({
    all_hotel_page: z.object({
      items: z.array(
        z
          .object({
            url: z.string(),
            hotel_page_id: z.string(),
            system: systemSchema,
          })
          .transform((data) => {
            return {
              url: removeMultipleSlashes(`/${data.system.locale}/${data.url}`),
              hotelId: data.hotel_page_id,
            }
          })
      ),
    }),
  })
  .transform(({ all_hotel_page }) => all_hotel_page.items)

export const batchedHotelPageUrlsSchema = z
  .array(
    z.object({
      data: hotelPageUrlsSchema,
    })
  )
  .transform((allItems) => {
    return allItems.flatMap((item) => item.data)
  })

export const hotelPageCountSchema = z
  .object({
    all_hotel_page: z.object({
      total: z.number(),
    }),
  })
  .transform(({ all_hotel_page }) => all_hotel_page.total)
