import { type NextMiddleware, NextResponse } from "next/server"

import {
  myPages,
  overview,
  profile,
  profileEdit,
} from "@/constants/routes/myPages"
import { notFound } from "@/server/errors/next"
import { getPublicNextURL } from "@/server/utils"

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

import { getDefaultRequestHeaders } from "./utils"

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) {
    const nextUrlPublic = getPublicNextURL(request)
    const overviewUrl = overview[lang]
    const redirectUrl = new URL(overviewUrl, nextUrlPublic)
    console.log(`[myPages] redirecting to: ${redirectUrl}`)
    return NextResponse.redirect(redirectUrl, {
      status: 308,
    })
  }

  const pathNameWithoutLang = nextUrl.pathname.replace(`/${lang}`, "")
  const { uid, contentType } = await resolveEntry(pathNameWithoutLang, lang)
  if (!uid || !contentType) {
    throw notFound(
      `Unable to resolve CMS entry for locale "${lang}": ${pathNameWithoutLang}`
    )
  }

  const headers = getDefaultRequestHeaders(request)
  headers.set("x-uid", uid)
  headers.set("x-contenttype", contentType)

  // Handle profile and profile edit routes, which are not CMS entries
  if (profile[lang].startsWith(nextUrl.pathname)) {
    return NextResponse.rewrite(new URL(`/${lang}/my-pages/profile`, nextUrl), {
      request: {
        headers,
      },
    })
  } else if (profileEdit[lang].startsWith(nextUrl.pathname)) {
    return NextResponse.rewrite(
      new URL(`/${lang}/my-pages/profile/edit`, nextUrl),
      {
        request: {
          headers,
        },
      }
    )
  }

  return NextResponse.next({
    request: {
      headers,
    },
  })
}

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