import { match } from '@formatjs/intl-localematcher'
import Negotiator from 'negotiator'
import type { UserSession } from '@heygermany/functions/src/application-types.d.js'
import type { DB, UserRole, UserType } from '@heygermany/sdk'
import { UserTypes } from '@heygermany/sdk'
import type { SupportedLocale } from '@heygermany/sdk/config'
import { LOCALES, DEFAULT_LOCALE } from '@/config'

type RequestSnapshot = {
  url: string
  pathname: string
  search: string
  headers: Headers
  cookies: Map<string, string>
}

type RequestRoutingResult =
  | {
      type: 'redirect'
      location: string
    }
  | {
      type: 'continue'
      locale: string
    }

const LOCALE_EXEMPT_PREFIXES = ['/pilot']
const LOCALE_EXEMPT_LOCALES: Record<string, SupportedLocale> = {
  '/pilot': 'de',
}

const getApiBase = (request: RequestSnapshot) => {
  return process.env.VITE_API_BASE_URL || process.env.API_URL || new URL(request.url).origin
}

function shouldBypassRouting(pathname: string): boolean {
  return (
    pathname.startsWith('/api/') ||
    pathname === '/api' ||
    pathname.startsWith('/_build/') ||
    pathname === '/_build' ||
    pathname.startsWith('/_serverFn/') ||
    pathname === '/_serverFn' ||
    pathname.startsWith('/@') ||
    pathname.startsWith('/src/') ||
    pathname.startsWith('/node_modules/') ||
    /\.[a-z0-9]+$/i.test(pathname)
  )
}

const getCookieHeader = (cookies: Map<string, string>) => {
  return Array.from(cookies.entries())
    .map(([name, value]) => `${name}=${value}`)
    .join('; ')
}

const getBetterAuthSession = async (
  request: RequestSnapshot
): Promise<UserSession | null> => {
  let response: Response
  try {
    response = await fetch(`${getApiBase(request)}/api/auth/get-session`, {
      method: 'GET',
      headers: {
        cookie: getCookieHeader(request.cookies),
      },
    })
  } catch (error) {
    // The session lookup must never crash SSR — a transient backend outage or
    // unreachable API should degrade to "logged out", not 500 the whole page.
    console.warn('[request-routing] get-session fetch failed, treating as no session:', error)
    return null
  }

  if (!response.ok) {
    return null
  }

  const data = (await response.json()) as {
    user?: {
      id: string
      name: string
      role: UserRole
      type: UserType
    } | null
  } | null

  if (!data?.user) {
    return null
  }

  return {
    userId: data.user.id,
    name: data.user.name,
    role: data.user.role,
    type: data.user.type,
  }
}

function getLocale(request: RequestSnapshot): string {
  try {
    const cookieLocale = request.cookies.get('NEXT_LOCALE')
    if (cookieLocale && LOCALES.includes(cookieLocale as SupportedLocale)) {
      return cookieLocale
    }

    const headers = Object.fromEntries(request.headers.entries()) as Negotiator.Headers
    const languages = new Negotiator({ headers }).languages()
    const validLanguages = languages.filter((lang) => {
      try {
        Intl.getCanonicalLocales(lang)
        return true
      } catch {
        return false
      }
    })

    if (validLanguages.length === 0) {
      return DEFAULT_LOCALE
    }

    return match(validLanguages, LOCALES, DEFAULT_LOCALE)
  } catch (error) {
    console.error('[Middleware] Error in locale detection:', error)
    return DEFAULT_LOCALE
  }
}

function hasLocale(pathname: string): boolean {
  return LOCALES.some((locale) => pathname.startsWith(`/${locale}/`) || pathname === `/${locale}`)
}

function isLocaleExemptPath(pathname: string): boolean {
  return LOCALE_EXEMPT_PREFIXES.some((prefix) => pathname === prefix || pathname.startsWith(`${prefix}/`))
}

function getLocaleExemptPathLocale(pathname: string): SupportedLocale | null {
  for (const [prefix, locale] of Object.entries(LOCALE_EXEMPT_LOCALES)) {
    if (pathname === prefix || pathname.startsWith(`${prefix}/`)) {
      return locale
    }
  }

  return null
}

function getLocaleFromPath(pathname: string): string | null {
  for (const locale of LOCALES) {
    if (pathname.startsWith(`/${locale}/`) || pathname === `/${locale}`) {
      return locale
    }
  }

  return null
}

function removeLocalePrefix(pathname: string): string {
  const locale = getLocaleFromPath(pathname)
  if (locale) {
    return pathname.slice(`/${locale}`.length) || '/'
  }

  return pathname
}

function requiresAuth(pathname: string): { required: boolean; type?: DB.UserType } {
  const pathWithoutLocale = removeLocalePrefix(pathname)

  if (pathWithoutLocale.includes('/auth/login')) {
    return { required: false }
  }

  if (pathWithoutLocale.startsWith('/backoffice')) {
    return { required: true, type: UserTypes.BACKOFFICE }
  }

  if (pathWithoutLocale.startsWith('/company')) {
    return { required: true, type: UserTypes.COMPANY }
  }

  if (pathWithoutLocale.startsWith('/jobs/application')) {
    return { required: true, type: UserTypes.CANDIDATE }
  }

  return { required: false }
}

const toAbsoluteUrl = (request: RequestSnapshot, location: string) => {
  return new URL(location, request.url).toString()
}

export const getResolvedLocale = (pathname: string) => {
  return getLocaleFromPath(pathname) || getLocaleExemptPathLocale(pathname) || DEFAULT_LOCALE
}

export async function resolveRequestRouting(
  request: RequestSnapshot
): Promise<RequestRoutingResult> {
  if (shouldBypassRouting(request.pathname)) {
    return {
      type: 'continue',
      locale: getResolvedLocale(request.pathname),
    }
  }

  const fullUrl = request.pathname + request.search

  if (!hasLocale(request.pathname) && !isLocaleExemptPath(request.pathname)) {
    const locale = getLocale(request)
    return {
      type: 'redirect',
      location: toAbsoluteUrl(request, `/${locale}${request.pathname}${request.search}`),
    }
  }

  const userSession = await getBetterAuthSession(request)
  const authCheck = requiresAuth(request.pathname)

  if (authCheck.required) {
    const currentLocale = getLocaleFromPath(request.pathname) || DEFAULT_LOCALE

    if (userSession?.type !== UserTypes.BACKOFFICE) {
      if (!userSession || userSession.type !== authCheck.type) {
        let loginPath = ''
        if (authCheck.type === UserTypes.BACKOFFICE) {
          loginPath = `/${currentLocale}/backoffice/auth/login`
        } else if (authCheck.type === UserTypes.COMPANY) {
          loginPath = `/${currentLocale}/company/auth/login`
        } else if (authCheck.type === UserTypes.CANDIDATE) {
          loginPath = `/${currentLocale}/jobs/apply`
        }

        const returnUrl = encodeURIComponent(fullUrl)
        return {
          type: 'redirect',
          location: toAbsoluteUrl(request, `${loginPath}?return=${returnUrl}`),
        }
      }
    }
  }

  if (userSession) {
    const pathWithoutLocale = removeLocalePrefix(request.pathname)
    const currentLocale = getLocaleFromPath(request.pathname) || DEFAULT_LOCALE

    if (pathWithoutLocale.includes('/auth/login')) {
      let dashboardPath = ''
      if (userSession.type === UserTypes.BACKOFFICE) {
        dashboardPath = `/${currentLocale}/backoffice/candidates`
      } else if (userSession.type === UserTypes.COMPANY) {
        dashboardPath = `/${currentLocale}/company/candidates`
      } else if (userSession.type === UserTypes.CANDIDATE) {
        dashboardPath = `/${currentLocale}/jobs/application`
      }

      if (dashboardPath) {
        return {
          type: 'redirect',
          location: toAbsoluteUrl(request, dashboardPath),
        }
      }
    }
  }

  return {
    type: 'continue',
    locale: getResolvedLocale(request.pathname),
  }
}
