import { z } from "zod"

import { Lang } from "@/constants/languages"

import {
  JoinLoyaltyContactTypenameEnum,
  LoyaltyBlocksTypenameEnum,
  LoyaltyComponentEnum,
  SidebarTypenameEnum,
} from "@/types/components/loyalty/enums"
import { Embeds } from "@/types/requests/embeds"
import { PageLinkEnum } from "@/types/requests/pageLinks"
import { EdgesWithTotalCount } from "@/types/requests/utils/edges"
import { RTEDocument } from "@/types/rte/node"

const pageLink = z.object({
  edges: z.array(
    z.object({
      node: z.object({
        system: z.object({
          uid: z.string(),
          locale: z.nativeEnum(Lang),
        }),
        web: z
          .object({
            original_url: z.string().nullable(),
          })
          .nullable()
          .optional(),
        url: z.string(),
        title: z.string(),
        __typename: z.string().optional(),
      }),
    })
  ),
})

const loyaltyPageDynamicContent = z.object({
  __typename: z.literal(
    LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksDynamicContent
  ),
  dynamic_content: z.object({
    title: z.string().nullable(),
    subtitle: z.string().nullable(),
    component: z.nativeEnum(LoyaltyComponentEnum),
    link: z.object({
      text: z.string().nullable(),
      pageConnection: pageLink,
    }),
  }),
})

const loyaltyPageShortcuts = z.object({
  __typename: z.literal(LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksShortcuts),
  shortcuts: z.object({
    title: z.string().nullable(),
    preamble: z.string().nullable(),
    shortcuts: z.array(
      z.object({
        linkConnection: pageLink,
        text: z.string().nullable(),
        open_in_new_tab: z.boolean(),
      })
    ),
  }),
})

const cardBlock = z.object({
  heading: z.string().nullable(),
  body_text: z.string().nullable(),
  background_image: z.any(),
  scripted_top_title: z.string().nullable(),
  primary_button: z
    .object({
      is_contentstack_link: z.boolean(),
      cta_text: z.string().nullable(),
      open_in_new_tab: z.boolean(),
      external_link: z.object({
        title: z.string().nullable(),
        href: z.string().nullable(),
      }),
      linkConnection: pageLink,
    })
    .nullable(),
  secondary_button: z
    .object({
      is_contentstack_link: z.boolean(),
      cta_text: z.string().nullable(),
      open_in_new_tab: z.boolean().nullable(),
      external_link: z.object({
        title: z.string().nullable(),
        href: z.string().nullable(),
      }),
      linkConnection: pageLink,
    })
    .nullable(),

  system: z.object({
    locale: z.nativeEnum(Lang),
    uid: z.string(),
  }),
})

const loyaltyPageCards = z.object({
  __typename: z.literal(LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksCardsGrid),
  cards_grid: z.object({
    title: z.string().nullable(),
    preamble: z.string().nullable(),
    layout: z.enum(["twoColumnGrid", "threeColumnGrid", "twoPlusOne"]),
    theme: z.enum(["one", "two", "three"]).nullable(),
    cardConnection: z.object({
      edges: z.array(
        z.object({
          node: cardBlock,
        })
      ),
    }),
  }),
})

const loyaltyPageBlockTextContent = z.object({
  __typename: z.literal(LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksContent),
  content: z.object({
    content: z.object({
      embedded_itemsConnection: z.object({
        edges: z.array(z.any()),
        totalCount: z.number(),
      }),
      json: z.any(),
    }),
  }),
})

const loyaltyPageBlockItem = z.discriminatedUnion("__typename", [
  loyaltyPageDynamicContent,
  loyaltyPageBlockTextContent,
  loyaltyPageShortcuts,
  loyaltyPageCards,
])

const loyaltyPageSidebarTextContent = z.object({
  __typename: z.literal(SidebarTypenameEnum.LoyaltyPageSidebarContent),
  content: z.object({
    content: z.object({
      embedded_itemsConnection: z.object({
        edges: z.array(z.any()),
        totalCount: z.number(),
      }),
      json: z.any(),
    }),
  }),
})

const loyaltyPageJoinLoyaltyContact = z.object({
  __typename: z.literal(
    SidebarTypenameEnum.LoyaltyPageSidebarJoinLoyaltyContact
  ),
  join_loyalty_contact: z.object({
    title: z.string().nullable(),
    preamble: z.string().nullable(),
    contact: z.array(
      z.object({
        __typename: z.literal(
          JoinLoyaltyContactTypenameEnum.LoyaltyPageSidebarJoinLoyaltyContactBlockContactContact
        ),
        contact: z.object({
          display_text: z.string().nullable(),
          contact_field: z.string(),
        }),
      })
    ),
  }),
})

const loyaltyPageSidebarItem = z.discriminatedUnion("__typename", [
  loyaltyPageSidebarTextContent,
  loyaltyPageJoinLoyaltyContact,
])

export const validateLoyaltyPageSchema = z.object({
  loyalty_page: z.object({
    title: z.string(),
    heading: z.string().nullable(),
    blocks: z.array(loyaltyPageBlockItem).nullable(),
    sidebar: z.array(loyaltyPageSidebarItem).nullable(),
    system: z.object({ uid: z.string() }),
  }),
})

// Block types
type DynamicContentRaw = z.infer<typeof loyaltyPageDynamicContent>

export type DynamicContent = Omit<DynamicContentRaw, "dynamic_content"> & {
  dynamic_content: Omit<DynamicContentRaw["dynamic_content"], "link"> & {
    link:
      | {
          href: string
          title: string
          text?: string
        }
      | undefined
  }
}
type BlockContentRaw = z.infer<typeof loyaltyPageBlockTextContent>

export interface RteBlockContent extends BlockContentRaw {
  content: {
    content: {
      json: RTEDocument
      embedded_itemsConnection: EdgesWithTotalCount<Embeds>
    }
  }
}

type CardsGridRaw = z.infer<typeof loyaltyPageCards>

export type CardsRaw =
  CardsGridRaw["cards_grid"]["cardConnection"]["edges"][number]["node"]

export type CardsGrid = Omit<CardsGridRaw, "cards_grid"> & {
  cards_grid: Omit<CardsGridRaw["cards_grid"], "cardConnection"> & {
    cards: (Omit<CardsRaw, "primaryButton" | "secondaryButton"> & {
      primaryButton:
        | {
            openInNewTab: boolean
            title: string
            href: string
            isExternal: boolean
          }
        | undefined
      secondaryButton:
        | {
            openInNewTab: boolean
            title: string
            href: string
            isExternal: boolean
          }
        | undefined
    })[]
  }
}

type ShortcutsRaw = z.infer<typeof loyaltyPageShortcuts>

export type Shortcuts = Omit<ShortcutsRaw, "shortcuts"> & {
  shortcuts: Omit<ShortcutsRaw["shortcuts"], "shortcuts"> & {
    shortcuts: {
      text?: string
      openInNewTab: boolean
      url: string
      title: string
    }[]
  }
}

export type Block = RteBlockContent | DynamicContent | Shortcuts | CardsGrid

// Sidebar block types
type SidebarContentRaw = z.infer<typeof loyaltyPageSidebarTextContent>

export type RteSidebarContent = Omit<SidebarContentRaw, "content"> & {
  content: {
    content: {
      json: RTEDocument
      embedded_itemsConnection: EdgesWithTotalCount<Embeds>
    }
  }
}
export type JoinLoyaltyContact = z.infer<typeof loyaltyPageJoinLoyaltyContact>
export type Sidebar = JoinLoyaltyContact | RteSidebarContent

export type LoyaltyPageDataRaw = z.infer<typeof validateLoyaltyPageSchema>

type LoyaltyPageRaw = LoyaltyPageDataRaw["loyalty_page"]

export type LoyaltyPage = Omit<LoyaltyPageRaw, "blocks" | "sidebar"> & {
  blocks: Block[]
  sidebar: Sidebar[]
}

// Refs types
const pageConnectionRefs = z.object({
  edges: z.array(
    z.object({
      node: z.object({
        __typename: z.nativeEnum(PageLinkEnum),
        system: z.object({
          content_type_uid: z.string(),
          uid: z.string(),
        }),
      }),
    })
  ),
})

const cardBlockRefs = z.object({
  primary_button: z
    .object({
      linkConnection: pageConnectionRefs,
    })
    .nullable(),
  secondary_button: z
    .object({
      linkConnection: pageConnectionRefs,
    })
    .nullable(),

  system: z.object({
    content_type_uid: z.string(),
    uid: z.string(),
  }),
})

const loyaltyPageCardsRefs = z.object({
  __typename: z.literal(LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksCardsGrid),
  cards_grid: z.object({
    cardConnection: z.object({
      edges: z.array(
        z.object({
          node: cardBlockRefs,
        })
      ),
    }),
  }),
})

const loyaltyPageDynamicContentRefs = z.object({
  __typename: z.literal(
    LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksDynamicContent
  ),
  dynamic_content: z.object({
    link: z.object({
      pageConnection: pageConnectionRefs,
    }),
  }),
})

const loyaltyPageShortcutsRefs = z.object({
  __typename: z.literal(LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksShortcuts),
  shortcuts: z.object({
    shortcuts: z.array(
      z.object({
        linkConnection: pageConnectionRefs,
      })
    ),
  }),
})

const loyaltyPageBlockTextContentRefs = z.object({
  __typename: z.literal(LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksContent),
  content: z.object({
    content: z.object({
      embedded_itemsConnection: pageConnectionRefs,
    }),
  }),
})

const loyaltyPageBlocRefsItem = z.discriminatedUnion("__typename", [
  loyaltyPageDynamicContentRefs,
  loyaltyPageBlockTextContentRefs,
  loyaltyPageShortcutsRefs,
  loyaltyPageCardsRefs,
])

const loyaltyPageSidebarTextContentRef = z.object({
  __typename: z.literal(SidebarTypenameEnum.LoyaltyPageSidebarContent),
  content: z.object({
    content: z.object({
      embedded_itemsConnection: pageConnectionRefs,
    }),
  }),
})

const loyaltyPageSidebarRefsItem = z.discriminatedUnion("__typename", [
  loyaltyPageSidebarTextContentRef,
])

export const validateLoyaltyPageRefsSchema = z.object({
  loyalty_page: z.object({
    blocks: z.array(loyaltyPageBlocRefsItem).nullable(),
    sidebar: z.array(loyaltyPageSidebarRefsItem).nullable(),
    system: z.object({
      content_type_uid: z.string(),
      uid: z.string(),
    }),
  }),
})

export type LoyaltyPageRefsDataRaw = z.infer<
  typeof validateLoyaltyPageRefsSchema
>
