import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

const WEBSITE_URL = process.env.NEXT_PUBLIC_WEBSITE_URL ?? 'http://localhost:3000'
const DASHBOARD_BASE_PATH = '/dashboard'

function toDashboardAppPath(pathname: string): string {
  let normalized = pathname || '/'

  while (normalized === DASHBOARD_BASE_PATH || normalized.startsWith(`${DASHBOARD_BASE_PATH}/`)) {
    normalized = normalized.slice(DASHBOARD_BASE_PATH.length) || '/'
  }

  return normalized
}

function toPublicDashboardPath(pathname: string): string {
  const appPath = toDashboardAppPath(pathname)
  return appPath === '/' ? DASHBOARD_BASE_PATH : `${DASHBOARD_BASE_PATH}${appPath}`
}

function deduplicatePublicDashboardPath(pathname: string): string | null {
  if (!pathname.startsWith(`${DASHBOARD_BASE_PATH}${DASHBOARD_BASE_PATH}`)) return null

  let normalized = pathname
  while (normalized.startsWith(`${DASHBOARD_BASE_PATH}${DASHBOARD_BASE_PATH}`)) {
    normalized = normalized.slice(DASHBOARD_BASE_PATH.length)
  }
  return normalized || DASHBOARD_BASE_PATH
}

function resolveProxyUrl(req: NextRequest, pathname: string): URL {
  const forwardedHost = req.headers.get('x-forwarded-host')
  const forwardedProto = req.headers.get('x-forwarded-proto')
  const websiteOrigin = new URL(WEBSITE_URL)

  const url = new URL(pathname, req.nextUrl.origin)
  if (forwardedHost && !isInternalHost(forwardedHost)) {
    url.host = forwardedHost
    url.protocol = (forwardedProto ?? 'http') + ':'
    if (!hasExplicitPort(forwardedHost) || isInternalAppPort(url.port)) url.port = ''
  } else if (!isInternalHost(req.nextUrl.host)) {
    url.host = req.nextUrl.host
    url.protocol = req.nextUrl.protocol
    if (!hasExplicitPort(req.nextUrl.host) || isInternalAppPort(url.port)) url.port = ''
  } else {
    url.host = websiteOrigin.host
    url.protocol = websiteOrigin.protocol
    if (!hasExplicitPort(websiteOrigin.host) || isInternalAppPort(url.port)) url.port = ''
  }
  return url
}

function hasExplicitPort(host: string): boolean {
  return /^[^:]+:\d+$/.test(host)
}

function isInternalAppPort(port: string): boolean {
  return ['3000', '3001', '3002', '3004', '4000'].includes(port)
}

function isInternalHost(host: string | null): boolean {
  if (!host) return false
  const hostname = host.split(':')[0]?.toLowerCase()
  return ['host.docker.internal', 'dashboard', 'admin', 'api', 'homepage', 'carplace'].includes(hostname)
}

function isProtectedRoute(req: NextRequest) {
  const pathname = toDashboardAppPath(req.nextUrl.pathname)
  if (pathname === '/api' || pathname.startsWith('/api/') || pathname === '/trpc' || pathname.startsWith('/trpc/')) return false
  if (['/sign-in', '/sign-up', '/forgot-password', '/reset-password', '/onboarding', '/verify-email'].some((p) => pathname === p || pathname.startsWith(p + '/'))) return false
  return pathname === '/' || (pathname.startsWith('/') && !pathname.startsWith('/_next'))
}

function localJwtMiddleware(req: NextRequest): NextResponse {
  const token = req.cookies.get('employee_session')?.value
  const pathname = toDashboardAppPath(req.nextUrl.pathname)

  // Redirect signed-in users from sign-in to dashboard (through the website proxy)
  if (token && pathname === '/sign-in') {
    const dashboardUrl = resolveProxyUrl(req, DASHBOARD_BASE_PATH)
    return NextResponse.redirect(dashboardUrl)
  }

  if (!isProtectedRoute(req)) return NextResponse.next()

  if (!token) {
    const signInUrl = resolveProxyUrl(req, toPublicDashboardPath('/sign-in'))
    signInUrl.searchParams.set('redirect', toPublicDashboardPath(req.nextUrl.pathname))
    return NextResponse.redirect(signInUrl)
  }
  return NextResponse.next()
}

export default function middleware(req: NextRequest) {
  if (req.headers.has('x-middleware-subrequest')) {
    return new NextResponse('Unsupported internal request header', { status: 400 })
  }

  const dedupedPath = deduplicatePublicDashboardPath(req.nextUrl.pathname)
  if (dedupedPath) {
    const redirectUrl = req.nextUrl.clone()
    redirectUrl.pathname = dedupedPath
    return NextResponse.redirect(redirectUrl)
  }

  return localJwtMiddleware(req)
}

export const config = {
  matcher: [
    '/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)',
    '/(api|trpc)(.*)',
  ],
}
