import { Lang } from "@/constants/languages"
import { request } from "@/lib/graphql/request"
import { internalServerError, notFound } from "@/server/errors/trpc"

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

import { type BreadcrumbsRefs, getBreadcrumbsSchema, Page } from "./output"

import type { Edges } from "@/types/requests/utils/edges"
import type { NodeRefs } from "@/types/requests/utils/refs"

export function getConnections(refs: BreadcrumbsRefs) {
  const connections: Edges<NodeRefs>[] = []

  if (refs.web?.breadcrumbs) {
    connections.push(refs.web.breadcrumbs.parentsConnection)
  }

  return connections
}

export const affix = "breadcrumbs"

// TODO: Make these editable in CMS?
export const homeBreadcrumbs = {
  [Lang.da]: {
    href: "/da",
    title: "Hjem",
    uid: "da",
  },
  [Lang.de]: {
    href: "/de",
    title: "Heim",
    uid: "de",
  },
  [Lang.en]: {
    href: "/en",
    title: "Home",
    uid: "en",
  },
  [Lang.fi]: {
    href: "/fi",
    title: "Koti",
    uid: "fi",
  },
  [Lang.no]: {
    href: "/no",
    title: "Hjem",
    uid: "no",
  },
  [Lang.sv]: {
    href: "/sv",
    title: "Hem",
    uid: "sv",
  },
}

export type Variables = {
  locale: Lang
  uid: string
}

export async function getRefsResponse<T>(query: string, variables: Variables) {
  const refsResponse = await request<T>(query, variables, {
    cache: "force-cache",
    next: {
      tags: [generateRefsResponseTag(variables.locale, variables.uid, affix)],
    },
  })
  if (!refsResponse.data) {
    throw notFound(refsResponse)
  }

  return refsResponse
}

export function getTags(page: BreadcrumbsRefs, variables: Variables) {
  const connections = getConnections(page)
  const tags = generateTags(variables.locale, connections)
  tags.push(generateTag(variables.locale, page.system.uid, affix))
  return tags
}

export async function getResponse<T>(
  query: string,
  variables: Variables,
  tags: string[]
) {
  const response = await request<T>(query, variables, {
    cache: "force-cache",
    next: { tags },
  })
  if (!response.data) {
    throw notFound(response)
  }

  return response
}

export function getBreadcrumbs(page: Page, lang: Lang) {
  const parentBreadcrumbs = page.web.breadcrumbs.parentsConnection.edges.map(
    (breadcrumb) => {
      return {
        href: removeMultipleSlashes(
          `/${breadcrumb.node.system.locale}/${breadcrumb.node.url}`
        ),
        title: breadcrumb.node.web.breadcrumbs.title,
        uid: breadcrumb.node.system.uid,
      }
    }
  )

  const pageBreadcrumb = {
    title: page.web.breadcrumbs.title,
    uid: page.system.uid,
  }

  const breadcrumbs = [
    homeBreadcrumbs[lang],
    parentBreadcrumbs,
    pageBreadcrumb,
  ].flat()

  const validatedBreadcrumbs = getBreadcrumbsSchema.safeParse(breadcrumbs)
  if (!validatedBreadcrumbs.success) {
    throw internalServerError(validatedBreadcrumbs.error)
  }

  return validatedBreadcrumbs.data
}
