import { NextResponse } from "next/server"

import { findLang } from "@/constants/languages"
import { myPages, overview } from "@/constants/routes/myPages"
import { env } from "@/env/server"
import { internalServerError, notFound } from "@/server/errors/next"

import { resolve as resolveEntry } from "@/utils/entry"

import { getDefaultRequestHeaders } from "./utils"

import type { NextMiddleware } from "next/server"

import type { MiddlewareMatcher } from "@/types/middleware"

export const middleware: NextMiddleware = async (request) => {
  const { nextUrl } = request
  const lang = findLang(nextUrl.pathname)!

  const myPagesRoot = myPages[lang]
  if (nextUrl.pathname === myPagesRoot) {
    if (!env.PUBLIC_URL) {
      throw internalServerError("Missing value for env.PUBLIC_URL")
    }

    const publicUrl = new URL(env.PUBLIC_URL)
    const nextUrlClone = nextUrl.clone()
    nextUrlClone.host = publicUrl.host
    nextUrlClone.hostname = publicUrl.hostname

    const overviewUrl = overview[lang]
    return NextResponse.redirect(new URL(overviewUrl, nextUrlClone))
  }

  const pathNameWithoutLang = nextUrl.pathname.replace(`/${lang}`, "")
  const { uid } = await resolveEntry(pathNameWithoutLang, lang)

  if (!uid) {
    throw notFound(
      `Unable to resolve CMS entry for locale "${lang}": ${pathNameWithoutLang}`
    )
  }

  const headers = getDefaultRequestHeaders(request)
  headers.set("x-uid", uid)
  return NextResponse.next({
    request: {
      headers,
    },
  })
}

export const matcher: MiddlewareMatcher = (request) => {
  const lang = findLang(request.nextUrl.pathname)!
  return request.nextUrl.pathname.startsWith(myPages[lang])
}
