import { MutationHook } from '@commerce/utils/types'
import useLogout, { UseLogout } from '@commerce/auth/use-logout'
import type { LogoutHook } from '@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
  },
}