import { MutationHook } from '@vercel/commerce/utils/types'
import useLogout, { UseLogout } from '@vercel/commerce/auth/use-logout'
import type { LogoutHook } from '@vercel/commerce/types/logout'
import { useCallback } from 'react'
import useCustomer from '../customer/use-customer'
import useCart from '../cart/use-cart'
import useWishlist from '../wishlist/use-wishlist'
import {
  ensureUserTokenResponse,
  removeUserTokenResponse,
} from '../utils/tokens/user-token-response'
import revokeUserTokens from '../utils/tokens/revoke-user-tokens'
import TokensNotRejectedError from '../errors/TokensNotRejectedError'

export default useLogout as UseLogout<typeof handler>

export const handler: MutationHook<LogoutHook> = {
  // Provide fetchOptions for SWR cache key
  fetchOptions: {
    url: 'authentication',
    query: 'revokeToken',
  },
  async fetcher({ input, options, fetch }) {
    console.info(
      'useLogout fetcher called. Configuration: ',
      'input: ',
      input,
      'options: ',
      options
    )

    const userToken = ensureUserTokenResponse()

    if (userToken) {
      try {
        // Revoke any tokens associated with the logged in user.
        await revokeUserTokens(fetch, {
          accessToken: userToken.access_token,
          refreshToken: userToken.refresh_token,
        })
      } catch (revokeUserTokenError) {
        // Squash token revocation errors and rethrow anything else.
        if (!(revokeUserTokenError instanceof TokensNotRejectedError)) {
          throw revokeUserTokenError
        }
      }

      // Whether token revocation succeeded or not, remove them from local storage.
      removeUserTokenResponse()
    }

    return null
  },
  useHook: ({ fetch }) => {
    const useWrappedHook: ReturnType<
      MutationHook<LogoutHook>['useHook']
    > = () => {
      const customer = useCustomer({
        swrOptions: { isPaused: () => true },
      })
      const cart = useCart({
        swrOptions: { isPaused: () => true },
      })
      const wishlist = useWishlist({
        swrOptions: { isPaused: () => true },
      })

      return useCallback(async () => {
        const data = await fetch()

        await customer.mutate(null, false)
        await cart.mutate(null, false)
        await wishlist.mutate(null, false)

        return data
      }, [customer, cart, wishlist])
    }

    return useWrappedHook
  },
}