// tdd-guard:skip — middleware helper; no isolated unit test without full Next.js request mock.
// Single-tenant: checkIsPlatformOwnerFromClaims + owner portal guard removed (2026-05-26).
import { createServerClient } from '@supabase/ssr'
import { NextResponse, type NextRequest } from 'next/server'

export interface UpdateSessionOptions {
  // Extra headers to attach to the forwarded request (e.g. CSP `x-nonce`).
  // Set by the top-level proxy so server components can read them via
  // `headers()` during SSR. Must be applied on every `NextResponse.next()`
  // call below — otherwise Supabase's cookie-refresh path silently drops them.
  extraRequestHeaders?: Headers
}

export async function updateSession(
  request: NextRequest,
  options: UpdateSessionOptions = {},
) {
  const buildRequestInit = () => {
    if (!options.extraRequestHeaders) return { request }
    const forwarded = new Headers(request.headers)
    options.extraRequestHeaders.forEach((value, key) => {
      forwarded.set(key, value)
    })
    return { request: { headers: forwarded } }
  }

  let supabaseResponse = NextResponse.next(buildRequestInit())

  // With Fluid compute, don't put this client in a global environment
  // variable. Always create a new one on each request.
  const supabase = createServerClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY!,
    {
      cookies: {
        getAll() {
          return request.cookies.getAll()
        },
        setAll(cookiesToSet) {
          cookiesToSet.forEach(({ name, value }) => request.cookies.set(name, value))
          supabaseResponse = NextResponse.next(buildRequestInit())
          cookiesToSet.forEach(({ name, value, options }) =>
            supabaseResponse.cookies.set(name, value, options)
          )
        },
      },
    }
  )

  // Do not run code between createServerClient and
  // supabase.auth.getClaims(). A simple mistake could make it very hard to debug
  // issues with users being randomly logged out.

  // IMPORTANT: If you remove getClaims() and you use server-side rendering
  // with the Supabase client, your users may be randomly logged out.
  const { data } = await supabase.auth.getClaims()

  const user = data?.claims

  // Single-tenant: owner portal guard removed — /owner and /api/owner
  // routes have been deleted. Only the standard auth redirect remains below.

  if (
    !user &&
    !request.nextUrl.pathname.startsWith('/login') &&
    !request.nextUrl.pathname.startsWith('/signup') &&
    !request.nextUrl.pathname.startsWith('/forgot-password') &&
    !request.nextUrl.pathname.startsWith('/reset-password') &&
    !request.nextUrl.pathname.startsWith('/auth') &&
    // C1 (KAR-698): Public-Submit-Route ist bewusst anonym erreichbar — die
    // Token-Validierung läuft in der RPC (get_intake_submission_form). Ohne
    // diese Ausnahme würde der externe Fachbereich zu /login umgeleitet.
    !request.nextUrl.pathname.startsWith('/intake/submit')
  ) {
    // no user, potentially respond by redirecting the user to the login page.
    // ?next= trägt das ursprüngliche Ziel (Pfad + Query) mit, damit der Login
    // dorthin zurückführt statt auf den /projektanlage-Fallback (Kais-Befund
    // 22.07.2026: Deep-Link /wertstrom ohne Session strandete dort). Der
    // Login validiert den Wert über safeRedirectPath (SEC-004). Die alte
    // Original-Query wird NICHT nackt an /login gehängt (sie gehört ins
    // next-Ziel, nicht an die Login-Seite). API-Pfade bekommen kein next —
    // nach dem Login auf einer JSON-Route zu landen hilft niemandem.
    const url = request.nextUrl.clone()
    const target = request.nextUrl.pathname + request.nextUrl.search
    url.pathname = '/login'
    url.search = ''
    if (target !== '/' && !request.nextUrl.pathname.startsWith('/api/')) {
      url.searchParams.set('next', target)
    }
    return NextResponse.redirect(url)
  }

  // must_change_password enforcement — runs for authenticated users only
  // Skip: auth routes, API routes, static assets, the change-password page itself
  const pathname = request.nextUrl.pathname
  const skipPwdCheck =
    !user ||
    pathname === '/auth/change-password' ||
    pathname.startsWith('/auth/') ||
    pathname.startsWith('/login') ||
    pathname.startsWith('/signup') ||
    pathname.startsWith('/forgot-password') ||
    pathname.startsWith('/reset-password') ||
    pathname.startsWith('/api/') ||
    pathname.startsWith('/_next/')

  if (!skipPwdCheck) {
    const { data: profile } = await supabase
      .from('user_profiles')
      .select('must_change_password')
      .eq('auth_user_id', user.sub as string)
      .maybeSingle()

    if (profile?.must_change_password === true) {
      const url = request.nextUrl.clone()
      url.pathname = '/auth/change-password'
      return NextResponse.redirect(url)
    }
  }

  // IMPORTANT: You *must* return the supabaseResponse object as it is. If you're
  // creating a new response object with NextResponse.next() make sure to:
  // 1. Pass the request in it, like so:
  //    const myNewResponse = NextResponse.next({ request })
  // 2. Copy over the cookies, like so:
  //    myNewResponse.cookies.setAll(supabaseResponse.cookies.getAll())
  // 3. Change the myNewResponse object to fit your needs, but avoid changing
  //    the cookies!
  // 4. Finally:
  //    return myNewResponse
  // If this is not done, you may be causing the browser and server to go out
  // of sync and terminate the user's session prematurely!

  return supabaseResponse
}
