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

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

import {
  getNavigationSchema,
  navigationPayloadSchema,
  navigationRefsPayloadSchema,
} from "./output"
import { getConnections } from "./utils"

import type {
  GetNavigationMyPagesData,
  GetNavigationMyPagesRefsData,
  MenuItem,
  NavigationItem,
} from "@/types/requests/myPages/navigation"

export function mapMenuItems(navigationItems: NavigationItem[]) {
  return navigationItems.map(({ item }): MenuItem => {
    const { node } = item.pageConnection.edges[0]

    const menuItem: MenuItem = {
      lang: node.system.locale,
      linkText: item.link_text || node.title,
      uid: node.system.uid,
      url: removeMultipleSlashes(`/${node.system.locale}/${node.url}`),
    }

    if ("sub_items" in item) {
      menuItem.subItems = mapMenuItems(item.sub_items)
    }

    return menuItem
  })
}

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

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

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

    const validatedMyPagesNavigationRefs =
      navigationRefsPayloadSchema.safeParse(refsResponse.data)
    if (!validatedMyPagesNavigationRefs.success) {
      throw internalServerError(validatedMyPagesNavigationRefs.error)
    }

    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 },
      { next: { tags } }
    )

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

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

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

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

    const validatedNav = getNavigationSchema.safeParse(nav)
    if (!validatedNav.success) {
      throw internalServerError(validatedNav.error)
    }

    return validatedNav.data
  }),
})
