// Copied from https://github.com/atinux/nuxthub-better-auth

import { defu } from 'defu'
import type { RouteLocationNormalized } from '#vue-router'

type MiddlewareOptions =
  | false
  | {
      /**
       * Only apply auth middleware to guest or user
       */
      only?: 'guest' | 'user'
      /**
       * Redirect authenticated user to this route
       */
      redirectUserTo?: string
      /**
       * Redirect guest to this route
       */
      redirectGuestTo?: string
    }

declare module '#app' {
  interface PageMeta {
    auth?: MiddlewareOptions
  }
}

declare module 'vue-router' {
  interface RouteMeta {
    auth?: MiddlewareOptions
  }
}

export default defineNuxtRouteMiddleware(async (to: RouteLocationNormalized) => {
  // 1. If auth is disabled, skip middleware
  if (to.meta?.auth === false) {
    console.log('[1] Auth middleware disabled for this route:', to.path)
    return
  }
  const { loggedIn, options, fetchSession, isPublicPath } = useAuth()
  const { only, redirectUserTo, redirectGuestTo } = defu(to.meta?.auth, options)

  // 2. If guest mode, redirect if authenticated
  if (only === 'guest' && loggedIn.value) {
    console.log('[2] Guest mode: user is authenticated, redirecting to', redirectUserTo)
    if (to.path === redirectUserTo) {
      console.log('[2.1] Already at redirectUserTo:', redirectUserTo)
      return
    }
    return navigateTo(redirectUserTo)
  }

  // 3. If client-side, fetch session between each navigation
  if (import.meta.client) {
    console.log('[3] Client-side navigation, fetching session')
    try {
      await fetchSession(to.path)
    } catch (e) {
      console.error(e)
    }
  }

  // 4. If not authenticated, redirect to home or guest route
  if (!loggedIn.value) {
    if (isPublicPath(to.path)) {
      console.log('[4] Not authenticated, but route is public:', to.path)
      // Continue navigating to the public route
      return
    }
    // No public route, redirect to guest route
    console.log('[4.1] Not authenticated, redirecting to guest route:', redirectGuestTo)
    return navigateTo(redirectGuestTo)
  }
})
