export default defineNuxtPlugin(() => {
  // Only run on client side
  if (import.meta.server) return

  let refreshTimer: NodeJS.Timeout | null = null
  let isRefreshing = false
  let retryCount = 0
  const maxRetries = 3

  const scheduleTokenRefresh = (expiresAt: number) => {
    // Clear existing timer
    if (refreshTimer) {
      clearTimeout(refreshTimer)
      refreshTimer = null
    }

    // Calculate time until refresh (refresh 5 minutes before expiry)
    const refreshBuffer = 5 * 60 * 1000 // 5 minutes in milliseconds
    const timeUntilRefresh = expiresAt - Date.now() - refreshBuffer

    console.log('[AUTH_REFRESH] Scheduling token refresh in:', Math.max(0, timeUntilRefresh), 'ms')
    console.log('[AUTH_REFRESH] Token expires at:', new Date(expiresAt))
    console.log('[AUTH_REFRESH] Will refresh at:', new Date(expiresAt - refreshBuffer))

    // Only schedule if we have time left
    if (timeUntilRefresh > 0) {
      refreshTimer = setTimeout(async () => {
        if (isRefreshing) return
        
        try {
          isRefreshing = true
          console.log('[AUTH_REFRESH] Attempting automatic token refresh...')
          
          const response = await $fetch<{ success: boolean; expiresAt?: number }>('/api/auth/refresh', {
            method: 'POST',
            retry: 2,
            retryDelay: 1000
          })

          if (response.success && response.expiresAt) {
            console.log('[AUTH_REFRESH] Token refresh successful, scheduling next refresh')
            retryCount = 0 // Reset retry count on success
            scheduleTokenRefresh(response.expiresAt)
          } else {
            console.error('[AUTH_REFRESH] Token refresh failed, redirecting to login')
            await navigateTo('/login')
          }
        } catch (error: any) {
          console.error('[AUTH_REFRESH] Token refresh error:', error)
          
          // Implement exponential backoff retry
          if (retryCount < maxRetries) {
            retryCount++
            const retryDelay = Math.min(1000 * Math.pow(2, retryCount), 10000) // Max 10 seconds
            console.log(`[AUTH_REFRESH] Retrying refresh in ${retryDelay}ms (attempt ${retryCount}/${maxRetries})`)
            
            setTimeout(() => {
              if (!isRefreshing) {
                scheduleTokenRefresh(expiresAt)
              }
            }, retryDelay)
          } else {
            console.error('[AUTH_REFRESH] Max retries reached, redirecting to login')
            await navigateTo('/login')
          }
        } finally {
          isRefreshing = false
        }
      }, timeUntilRefresh)
    } else {
      // Token already expired or very close to expiry, try immediate refresh
      setTimeout(async () => {
        if (isRefreshing) return
        
        try {
          isRefreshing = true
          console.log('[AUTH_REFRESH] Token expired, attempting immediate refresh...')
          
          const response = await $fetch<{ success: boolean; expiresAt?: number }>('/api/auth/refresh', {
            method: 'POST',
            retry: 2,
            retryDelay: 1000
          })

          if (response.success && response.expiresAt) {
            console.log('[AUTH_REFRESH] Immediate refresh successful')
            retryCount = 0 // Reset retry count on success
            scheduleTokenRefresh(response.expiresAt)
          } else {
            console.error('[AUTH_REFRESH] Immediate refresh failed, redirecting to login')
            await navigateTo('/login')
          }
        } catch (error) {
          console.error('[AUTH_REFRESH] Immediate refresh error:', error)
          
          // Try one more time before giving up
          if (retryCount === 0) {
            retryCount++
            console.log('[AUTH_REFRESH] Retrying immediate refresh once more...')
            setTimeout(() => {
              if (!isRefreshing) {
                scheduleTokenRefresh(Date.now() - 1) // Force immediate refresh
              }
            }, 2000)
          } else {
            await navigateTo('/login')
          }
        } finally {
          isRefreshing = false
        }
      }, 100) // Small delay to avoid immediate execution
    }
  }

  const checkAndScheduleRefresh = async () => {
    try {
      // Use middleware cache instead of API call
      const nuxtApp = useNuxtApp()
      const authState = nuxtApp.payload?.data?.authState
      const sessionCache = nuxtApp.payload?.data?.['auth:session:cache']
      
      const sessionData = authState || sessionCache
      
      if (sessionData?.authenticated) {
        // Get the session cookie to extract expiry time
        const sessionCookie = useCookie('nuxt-oidc-auth')
        
        if (sessionCookie.value) {
          try {
            const parsedSession = typeof sessionCookie.value === 'string' 
              ? JSON.parse(sessionCookie.value) 
              : sessionCookie.value

            if (parsedSession.expiresAt) {
              console.log('[AUTH_REFRESH] Found session with expiry:', new Date(parsedSession.expiresAt))
              scheduleTokenRefresh(parsedSession.expiresAt)
            }
          } catch (parseError) {
            console.error('[AUTH_REFRESH] Failed to parse session cookie:', parseError)
          }
        }
      } else {
        console.log('[AUTH_REFRESH] No authenticated session found in cache')
      }
    } catch (error) {
      console.error('[AUTH_REFRESH] Failed to check session:', error)
    }
  }

  // Check authentication status and schedule refresh on plugin initialization
  onMounted(() => {
    checkAndScheduleRefresh()
  })

  // Listen for route changes to re-check auth status
  const router = useRouter()
  router.afterEach((to) => {
    // Only check on protected routes
    if (to.meta.auth !== false) {
      checkAndScheduleRefresh()
    }
  })

  // Listen for visibility changes to refresh when tab becomes active
  if (typeof document !== 'undefined') {
    let lastVisibilityChange = Date.now()
    
    document.addEventListener('visibilitychange', async () => {
      if (!document.hidden) {
        const now = Date.now()
        const timeSinceLastCheck = now - lastVisibilityChange
        
        // If tab was hidden for more than 30 seconds, check auth status
        if (timeSinceLastCheck > 30000) {
          console.log('[AUTH_REFRESH] Tab became visible after', Math.round(timeSinceLastCheck / 1000), 'seconds, checking auth status')
          
          // Force immediate session validation
          try {
            const response = await fetch('/api/auth/session', {
              headers: {
                'Cache-Control': 'no-cache',
                'Pragma': 'no-cache'
              }
            })
            
            if (!response.ok || response.status === 401) {
              console.log('[AUTH_REFRESH] Session expired while tab was hidden')
              await navigateTo('/login')
              return
            }
            
            const sessionData = await response.json()
            if (!sessionData.authenticated) {
              console.log('[AUTH_REFRESH] Not authenticated after tab visibility')
              await navigateTo('/login')
              return
            }
            
            // Re-schedule refresh if session is valid
            checkAndScheduleRefresh()
          } catch (error) {
            console.error('[AUTH_REFRESH] Failed to check session on visibility change:', error)
            await navigateTo('/login')
          }
        }
        
        lastVisibilityChange = now
      }
    })
  }

  // Add periodic session validation (every 2 minutes)
  let validationInterval: NodeJS.Timeout | null = null
  
  onMounted(() => {
    validationInterval = setInterval(async () => {
      console.log('[AUTH_REFRESH] Performing periodic session validation')
      
      try {
        const response = await fetch('/api/auth/session', {
          headers: {
            'Cache-Control': 'no-cache',
            'Pragma': 'no-cache'
          }
        })
        
        if (!response.ok || response.status === 401) {
          console.log('[AUTH_REFRESH] Session invalid during periodic check')
          clearInterval(validationInterval!)
          await navigateTo('/login')
        }
      } catch (error) {
        console.error('[AUTH_REFRESH] Periodic validation error:', error)
      }
    }, 2 * 60 * 1000) // Every 2 minutes
  })

  // Clean up timers on plugin destruction
  onBeforeUnmount(() => {
    if (refreshTimer) {
      clearTimeout(refreshTimer)
      refreshTimer = null
    }
    if (validationInterval) {
      clearInterval(validationInterval)
      validationInterval = null
    }
  })
})
