import {
  GetNavigationMyPages,
  GetNavigationMyPagesRefs,
} from "@/lib/graphql/Query/NavigationMyPages.graphql"
import { request } from "@/lib/graphql/request"
import { notFound } from "@/server/errors/trpc"
import { contentstackBaseProcedure, router } from "@/server/trpc"

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

import {
  type GetNavigationMyPagesData,
  type GetNavigationMyPagesRefsData,
  getNavigationSchema,
  type MenuItems,
  navigationPayloadSchema,
  navigationRefsPayloadSchema,
} from "./output"
import { getConnections } from "./utils"

import { PageLinkEnum } from "@/types/requests/pageLinks"

export function mapMenuItems(menuItems: MenuItems) {
  return menuItems.map((menuItem) => {
    return {
      ...menuItem,
      links: menuItem.links
        .filter((link) => {
          // If content is unpublished or in other way inaccessible in Contentstack
          // there will be no edges, filter out those links.
          return !!link.page.edges[0]
        })
        .map((link) => {
          const page = link.page.edges[0].node
          let originalUrl = undefined
          if (
            page.__typename === PageLinkEnum.ContentPage ||
            page.__typename === PageLinkEnum.LoyaltyPage
          ) {
            if (page.web.original_url) {
              originalUrl = page.web.original_url
            }
          }
          return {
            lang: page.system.locale,
            linkText: link.link_text ? link.link_text : page.title,
            uid: page.system.uid,
            url: removeMultipleSlashes(`/${page.system.locale}/${page.url}`),
            originalUrl,
          }
        }),
    }
  })
}

export const navigationQueryRouter = router({
  get: contentstackBaseProcedure.query(async function ({ ctx }) {
    const { lang } = ctx

    const refsResponse = await request<GetNavigationMyPagesRefsData>(
      GetNavigationMyPagesRefs,
      { locale: lang },
      {
        tags: [generateRefsResponseTag(lang, "navigation_my_pages")],
      }
    )

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

    const validatedMyPagesNavigationRefs =
      navigationRefsPayloadSchema.safeParse(refsResponse.data)
    if (!validatedMyPagesNavigationRefs.success) {
      console.info(
        `Failed to validate My Pages Navigation Refs - (lang: ${lang}`
      )
      console.error(validatedMyPagesNavigationRefs.error)
      return null
    }

    const connections = getConnections(validatedMyPagesNavigationRefs.data)

    const tags = [
      generateTags(lang, connections),
      generateTag(
        lang,
        validatedMyPagesNavigationRefs.data.all_navigation_my_pages.items[0]
          .system.uid
      ),
    ].flat()

    const response = await request<GetNavigationMyPagesData>(
      GetNavigationMyPages,
      { locale: lang },
      { tags }
    )

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

    const validatedMyPagesNavigation = navigationPayloadSchema.safeParse(
      response.data
    )
    if (!validatedMyPagesNavigation.success) {
      console.info(
        `Failed to validate My Pages Navigation Data - (lang: ${lang}`
      )
      console.error(validatedMyPagesNavigation.error)
      return null
    }

    const menuItem =
      validatedMyPagesNavigation.data.all_navigation_my_pages.items[0]

    const nav = {
      menuItems: mapMenuItems(menuItem.menu_items),
      title: menuItem.title,
    }

    const validatedNav = getNavigationSchema.safeParse(nav)
    if (!validatedNav.success) {
      console.info(
        `Failed to validate My Pages Navigation Return Data - (lang: ${lang}`
      )
      console.error(validatedNav.error)
      return null
    }

    return validatedNav.data
  }),
})
