import { useRouter } from "next/navigation"
import { useCallback, useEffect, useState } from "react"
import { useIntl } from "react-intl"

import { BookingStatusEnum } from "@/constants/booking"
import { trpc } from "@/lib/trpc/client"

import { toast } from "@/components/TempDesignSystem/Toasts"
import { useHandleBookingStatus } from "@/hooks/booking/useHandleBookingStatus"
import { trackEvent } from "@/utils/tracking/base"

const maxRetries = 15
const retryInterval = 2000

export function useGuaranteeBooking(
  refId: string,
  isAncillaryFlow = false,
  hotelId: string
) {
  const intl = useIntl()
  const router = useRouter()
  const [isPollingForBookingStatus, setIsPollingForBookingStatus] =
    useState(false)

  const handleGuaranteeError = useCallback(
    (errorMessage?: string) => {
      trackEvent({
        event: "glaCardSaveFailed",
        hotelInfo: {
          hotelId,
          lateArrivalGuarantee: "yes",
          guaranteedProduct: isAncillaryFlow ? "room + ancillary" : "room",
        },
        paymentInfo: {
          status: "glacardsavefailed",
          errorMessage,
        },
      })
      toast.error(
        intl.formatMessage({
          defaultMessage:
            "We had an issue guaranteeing your booking. Please try again.",
        })
      )
    },
    [intl, isAncillaryFlow, hotelId]
  )

  const utils = trpc.useUtils()
  const guaranteeBooking = trpc.booking.guarantee.useMutation({
    onSuccess: (result) => {
      if (result) {
        const mainRoom = result.rooms[0]
        if (result.reservationStatus == BookingStatusEnum.BookingCompleted) {
          utils.booking.get.invalidate({ refId: mainRoom.refId })
        } else {
          setIsPollingForBookingStatus(true)
          utils.booking.status.invalidate({ refId: mainRoom.refId })
        }
      } else {
        handleGuaranteeError()
      }
    },
    onError: (error) => {
      handleGuaranteeError(error.message)
    },
  })

  const bookingStatus = useHandleBookingStatus({
    refId,
    expectedStatuses: [BookingStatusEnum.BookingCompleted],
    maxRetries,
    retryInterval,
    enabled: isPollingForBookingStatus,
  })

  useEffect(() => {
    if (bookingStatus?.data?.booking.paymentUrl && isPollingForBookingStatus) {
      router.push(bookingStatus.data.booking.paymentUrl)
      utils.booking.get.invalidate({ refId })
      setIsPollingForBookingStatus(false)
    } else if (bookingStatus.isTimeout) {
      handleGuaranteeError("Timeout")
    }
  }, [
    bookingStatus,
    router,
    handleGuaranteeError,
    setIsPollingForBookingStatus,
    isPollingForBookingStatus,
    refId,
    utils.booking.get,
  ])

  const isLoading =
    guaranteeBooking.isPending ||
    (isPollingForBookingStatus &&
      !bookingStatus.data?.booking.paymentUrl &&
      !bookingStatus.isTimeout)

  return {
    guaranteeBooking,
    isLoading,
    handleGuaranteeError,
  }
}
