import {
  GetLoyaltyPage,
  GetLoyaltyPageRefs,
} from "@/lib/graphql/Query/LoyaltyPage.graphql"
import { request } from "@/lib/graphql/request"
import { _ } from "@/lib/translation"
import { internalServerError, notFound } from "@/server/errors/trpc"
import { contentstackProcedure, router } from "@/server/trpc"

import {
  generateRefsResponseTag,
  generateTag,
  generateTags,
} from "@/utils/generateTag"

import { removeEmptyObjects } from "../../utils"
import {
  CardsRaw,
  type LoyaltyPage,
  type LoyaltyPageDataRaw,
  type LoyaltyPageRefsDataRaw,
  validateLoyaltyPageRefsSchema,
  validateLoyaltyPageSchema,
} from "./output"
import { getConnections } from "./utils"

import {
  LoyaltyBlocksTypenameEnum,
  SidebarTypenameEnum,
} from "@/types/components/loyalty/enums"
import { Embeds } from "@/types/requests/embeds"
import { Edges } from "@/types/requests/utils/edges"
import { RTEDocument } from "@/types/rte/node"

function makeButtonObject(
  button: CardsRaw["primary_button" | "secondary_button"]
) {
  if (!button) return undefined
  return {
    openInNewTab: button.open_in_new_tab,
    title:
      button.cta_text ||
      (button.is_contentstack_link && button.linkConnection.edges.length
        ? button.linkConnection.edges[0].node.title
        : button.external_link.title),
    href:
      button.is_contentstack_link && button.linkConnection.edges.length
        ? button.linkConnection.edges[0].node.web?.original_url ||
          `/${button.linkConnection.edges[0].node.system.locale}${button.linkConnection.edges[0].node.url}`
        : button.external_link.href,
    isExternal: !button.is_contentstack_link,
  }
}

export const loyaltyPageQueryRouter = router({
  get: contentstackProcedure.query(async ({ ctx }) => {
    const { lang, uid } = ctx

    const refsResponse = await request<LoyaltyPageRefsDataRaw>(
      GetLoyaltyPageRefs,
      {
        locale: lang,
        uid,
      },
      {
        next: {
          tags: [generateRefsResponseTag(lang, uid)],
        },
      }
    )

    if (!refsResponse.data) {
      throw notFound(refsResponse)
    }

    // Remove empty objects from a fetched content type. Needed since
    // Contentstack returns empty objects for all non queried blocks in modular blocks.
    // This is an ongoing support case in Contentstack, ticker number #00031579
    const cleanedData = removeEmptyObjects(refsResponse.data)

    const validatedLoyaltyPageRefs =
      validateLoyaltyPageRefsSchema.safeParse(cleanedData)
    if (!validatedLoyaltyPageRefs.success) {
      console.error("Bad validation for `GetLoyaltyPageRefs`")
      console.error(validatedLoyaltyPageRefs.error)
      throw internalServerError(validatedLoyaltyPageRefs.error)
    }

    const connections = getConnections(validatedLoyaltyPageRefs.data)

    const tags = [
      generateTags(lang, connections),
      generateTag(lang, validatedLoyaltyPageRefs.data.loyalty_page.system.uid),
    ].flat()

    const response = await request<LoyaltyPageDataRaw>(
      GetLoyaltyPage,
      {
        locale: lang,
        uid,
      },
      { next: { tags } }
    )

    if (!response.data) {
      throw notFound(response)
    }

    const validatedLoyaltyPage = validateLoyaltyPageSchema.safeParse(
      response.data
    )
    if (!validatedLoyaltyPage.success) {
      throw internalServerError(validatedLoyaltyPage.error)
    }

    const sidebar = validatedLoyaltyPage.data.loyalty_page.sidebar
      ? validatedLoyaltyPage.data.loyalty_page.sidebar.map((block) => {
          if (
            block.__typename == SidebarTypenameEnum.LoyaltyPageSidebarContent
          ) {
            return {
              ...block,
              content: {
                content: {
                  json: block.content.content.json as RTEDocument,
                  embedded_itemsConnection: block.content.content
                    .embedded_itemsConnection as Edges<Embeds>,
                },
              },
            }
          } else {
            return block
          }
        })
      : null

    const blocks = validatedLoyaltyPage.data.loyalty_page.blocks
      ? validatedLoyaltyPage.data.loyalty_page.blocks.map((block) => {
          switch (block.__typename) {
            case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksDynamicContent:
              return {
                ...block,
                dynamic_content: {
                  ...block.dynamic_content,
                  link: block.dynamic_content.link.pageConnection.edges.length
                    ? {
                        text: block.dynamic_content.link.text,
                        href: `/${block.dynamic_content.link.pageConnection.edges[0].node.system.locale}${block.dynamic_content.link.pageConnection.edges[0].node.url}`,
                        title:
                          block.dynamic_content.link.pageConnection.edges[0]
                            .node.title,
                      }
                    : undefined,
                },
              }
            case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksContent:
              return {
                ...block,
                content: {
                  content: {
                    json: block.content.content.json as RTEDocument,
                    embedded_itemsConnection: block.content.content
                      .embedded_itemsConnection as Edges<Embeds>,
                  },
                },
              }
            case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksShortcuts:
              return {
                ...block,
                shortcuts: {
                  ...block.shortcuts,
                  shortcuts: block.shortcuts.shortcuts.map((shortcut) => ({
                    text: shortcut.text,
                    openInNewTab: shortcut.open_in_new_tab,
                    ...shortcut.linkConnection.edges[0].node,
                    url:
                      shortcut.linkConnection.edges[0].node.web?.original_url ||
                      `/${shortcut.linkConnection.edges[0].node.system.locale}${shortcut.linkConnection.edges[0].node.url}`,
                  })),
                },
              }
            case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksCardsGrid:
              return {
                ...block,
                cards_grid: {
                  ...block.cards_grid,
                  cards: block.cards_grid.cardConnection.edges.map(
                    ({ node: card }) => {
                      return {
                        ...card,
                        primaryButton: makeButtonObject(card.primary_button),
                        secondaryButton: makeButtonObject(
                          card.secondary_button
                        ),
                      }
                    }
                  ),
                },
              }
            default:
              return block
          }
        })
      : null

    const loyaltyPage = {
      ...validatedLoyaltyPage.data.loyalty_page,
      blocks,
      sidebar,
    } as LoyaltyPage

    return loyaltyPage
  }),
})
