"use client"

import { usePathname, useSearchParams } from "next/navigation"
import { useEffect, useRef, useState } from "react"
import { useIntl } from "react-intl"

import { BookingErrorCodeEnum } from "@/constants/booking"
import { selectRate } from "@/constants/routes/hotelReservation"
import { useEnterDetailsStore } from "@/stores/enter-details"

import Alert from "@/components/TempDesignSystem/Alert"
import useLang from "@/hooks/useLang"
import useStickyPosition from "@/hooks/useStickyPosition"

import styles from "./bookingAlert.module.css"

import { AlertTypeEnum } from "@/types/enums/alert"

function useBookingErrorAlert() {
  const updateSearchParams = useEnterDetailsStore(
    (state) => state.actions.updateSeachParamString
  )
  const intl = useIntl()
  const lang = useLang()
  const searchParams = useSearchParams()
  const pathname = usePathname()

  const errorCode = searchParams.get("errorCode")
  const errorMessage = getErrorMessage(errorCode)
  const severityLevel =
    errorCode === BookingErrorCodeEnum.TransactionCancelled
      ? AlertTypeEnum.Warning
      : AlertTypeEnum.Alarm

  const [showAlert, setShowAlert] = useState(!!errorCode)

  const selectRateReturnUrl = getSelectRateReturnUrl()

  function getErrorMessage(errorCode: string | null) {
    switch (errorCode) {
      case BookingErrorCodeEnum.TransactionCancelled:
        return intl.formatMessage({
          defaultMessage: "You have now cancelled your payment.",
        })
      case BookingErrorCodeEnum.AvailabilityError:
        return intl.formatMessage({
          defaultMessage:
            "Unfortunately, one of the rooms you selected is sold out. Please choose another room to proceed.",
        })
      default:
        return intl.formatMessage({
          defaultMessage:
            "We had an issue processing your booking. Please try again. No charges have been made.",
        })
    }
  }

  function discardAlert() {
    setShowAlert(false)
    const queryParams = new URLSearchParams(searchParams.toString())
    queryParams.delete("errorCode")
    updateSearchParams(queryParams.toString())

    window.history.replaceState({}, "", `${pathname}?${queryParams.toString()}`)
  }

  function getSelectRateReturnUrl() {
    const queryParams = new URLSearchParams(searchParams.toString())
    queryParams.delete("errorCode")
    return `${selectRate(lang)}?${queryParams.toString()}`
  }

  return {
    showAlert,
    errorCode,
    errorMessage,
    severityLevel,
    discardAlert,
    setShowAlert,
    selectRateReturnUrl,
  }
}

interface BookingAlertProps {
  isVisible?: boolean
}

export default function BookingAlert({ isVisible = false }: BookingAlertProps) {
  const intl = useIntl()

  const {
    showAlert,
    errorCode,
    errorMessage,
    severityLevel,
    discardAlert,
    setShowAlert,
    selectRateReturnUrl,
  } = useBookingErrorAlert()

  const ref = useRef<HTMLDivElement>(null)
  const { getTopOffset } = useStickyPosition()

  useEffect(() => {
    if (isVisible) {
      setShowAlert(true)
    }
  }, [isVisible, setShowAlert])

  useEffect(() => {
    const el = ref.current

    if (showAlert && el) {
      window.scrollTo({
        top: el.offsetTop - getTopOffset(),
        behavior: "smooth",
      })
    }
  }, [showAlert, getTopOffset])

  if (!showAlert) return null

  const isAvailabilityError =
    errorCode === BookingErrorCodeEnum.AvailabilityError

  return (
    <div className={styles.wrapper} ref={ref}>
      <Alert
        type={severityLevel}
        variant="inline"
        text={errorMessage}
        close={discardAlert}
        link={
          isAvailabilityError
            ? {
                title: intl.formatMessage({
                  defaultMessage: "Change room",
                }),
                url: selectRateReturnUrl,
              }
            : undefined
        }
      />
    </div>
  )
}
