"use client"
import { usePathname, useSearchParams } from "next/navigation"
import { SessionProvider, useSession } from "next-auth/react"
import { useEffect, useMemo, useRef } from "react"

import {
  MAX_KEEP_ALIVE_TIME_IN_MINUTES,
  PRE_REFRESH_TIME_IN_SECONDS,
} from "@/constants/auth"

/**
 * Keeps the access token alive by proactively refreshing it
 *
 */
export default function TokenRefresher() {
  return (
    <SessionProvider basePath="/api/web/auth">
      <Refresher />
    </SessionProvider>
  )
}

function Refresher() {
  const session = useSession()
  const pathname = usePathname()
  const searchParams = useSearchParams()
  const timeoutId = useRef<NodeJS.Timeout>()

  // Simple inactivity control. Reset when the URL changes.
  const stopPreRefreshAt = useMemo(
    () => Date.now() + MAX_KEEP_ALIVE_TIME_IN_MINUTES * 60 * 1000,
    // eslint-disable-next-line react-hooks/exhaustive-deps
    [pathname, searchParams]
  )

  useEffect(() => {
    if (timeoutId.current) {
      clearTimeout(timeoutId.current)
    }

    if (!session.data?.token.expires_at) {
      return
    }

    const refreshIn =
      session.data.token.expires_at -
      Date.now() -
      PRE_REFRESH_TIME_IN_SECONDS * 1000

    timeoutId.current = setTimeout(
      async () => {
        if (stopPreRefreshAt > Date.now()) {
          await session.update({ doRefresh: true })
        }
      },
      // If the token has already expired `refreshIn` will be
      // negative, and we will refresh immediately (in 1 ms)
      Math.max(refreshIn, 1)
    )

    return () => clearTimeout(timeoutId.current)
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [session.data?.token.expires_at, stopPreRefreshAt])
  return null
}
