"use client"
import { useSearchParams } from "next/navigation"
import { useEffect } from "react"
import { useIntl } from "react-intl"

import { alternativeHotels } from "@/constants/routes/hotelReservation"
import { useBookingCodeFilterStore } from "@/stores/bookingCode-filter"
import { useRatesStore } from "@/stores/select-rate"

import BookingCodeFilter from "@/components/HotelReservation/SelectHotel/BookingCodeFilter"
import Alert from "@/components/TempDesignSystem/Alert"
import { useRoomContext } from "@/contexts/SelectRate/Room"
import useLang from "@/hooks/useLang"

import RoomCard from "./RoomCard"
import RoomTypeFilter from "./RoomTypeFilter"

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

import { AvailabilityEnum } from "@/types/components/hotelReservation/selectHotel/selectHotel"
import { AlertTypeEnum } from "@/types/enums/alert"
import { BookingCodeFilterEnum } from "@/types/enums/bookingCodeFilter"
import { RateTypeEnum } from "@/types/enums/rateType"

export default function RoomSelectionPanel() {
  const { rooms } = useRoomContext()
  const isSingleRoomAndHasSelection = useRatesStore(
    (state) => state.booking.rooms.length === 1 && !!state.rateSummary.length
  )
  const searchParams = useSearchParams()
  const bookingCode = searchParams.get("bookingCode")
  const intl = useIntl()
  const lang = useLang()
  const noAvailableRooms = rooms.every(
    (roomConfig) => roomConfig.status === AvailabilityEnum.NotAvailable
  )
  const activeCodeFilter = useBookingCodeFilterStore(
    (state) => state.activeCodeFilter
  )

  const isVoucherOrCorpChequeRate = rooms.find((room) =>
    room.products.some((product) => product.voucher || product.bonusCheque)
  )

  let isRegularRatesAvailableWithCode = false,
    isBookingCodeRatesAvailable = false
  let visibleRooms = rooms
  if (bookingCode && !isVoucherOrCorpChequeRate) {
    // Regular Rates (Save, Change and Flex) always should send both public and member rates
    // so we can check public rates for availability
    isRegularRatesAvailableWithCode = rooms.some(
      (room) =>
        room.status === AvailabilityEnum.Available &&
        room.products.some(
          (product) =>
            product.public?.rateType === RateTypeEnum.Regular ||
            product.member?.rateType === RateTypeEnum.Regular
        )
    )

    // Booking codes rate comes with various rate types but Regular is reserved
    // for non-booking code rates (Save, Change & Flex)
    // With Booking code rates we will always obtain public rate and maybe a member rate
    // so we check for public rate and ignore member rate
    isBookingCodeRatesAvailable = rooms.some(
      (room) =>
        room.status === AvailabilityEnum.Available &&
        room.products.some(
          (product) =>
            product.public?.rateType !== RateTypeEnum.Regular ||
            product.member?.rateType !== RateTypeEnum.Regular
        )
    )

    if (activeCodeFilter === BookingCodeFilterEnum.Discounted) {
      visibleRooms = rooms.filter(
        (room) =>
          room.status === AvailabilityEnum.Available &&
          room.products.every(
            (product) => product.public?.rateType !== RateTypeEnum.Regular
          )
      )
    } else if (activeCodeFilter === BookingCodeFilterEnum.Regular) {
      visibleRooms = rooms.filter(
        (room) =>
          room.status === AvailabilityEnum.Available &&
          room.products.every(
            (product) =>
              product.public?.rateType === RateTypeEnum.Regular ||
              product.member?.rateType === RateTypeEnum.Regular
          )
      )
    }
  }
  // Show booking code filter when both of the booking code rates or regular rates are available
  const showBookingCodeFilter =
    isRegularRatesAvailableWithCode && isBookingCodeRatesAvailable

  useEffect(() => {
    if (isSingleRoomAndHasSelection) {
      // Required to prevent the history.pushState on the first selection
      // to scroll user back to top
      requestAnimationFrame(() => {
        const SCROLL_OFFSET = 100
        const selectedInputRoomCard = document.querySelector(
          `.${styles.roomList} li:has(input[type=radio]:checked)`
        )
        if (selectedInputRoomCard) {
          const elementPosition =
            selectedInputRoomCard.getBoundingClientRect().top
          const offsetPosition =
            elementPosition + window.scrollY - SCROLL_OFFSET

          window.scrollTo({
            top: offsetPosition,
            behavior: "instant",
          })
        }
      })
    }
  }, [isSingleRoomAndHasSelection])

  return (
    <>
      {noAvailableRooms ||
      (bookingCode &&
        !isBookingCodeRatesAvailable &&
        !isVoucherOrCorpChequeRate) ? (
        <div className={styles.hotelAlert}>
          <Alert
            type={AlertTypeEnum.Info}
            heading={intl.formatMessage({ id: "No availability" })}
            text={
              bookingCode && !isBookingCodeRatesAvailable
                ? intl.formatMessage(
                    {
                      id: "We found no available rooms using this booking code ({bookingCode}). See available rates below.",
                    },
                    { bookingCode }
                  )
                : intl.formatMessage({
                    id: "There are no rooms available that match your request.",
                  })
            }
            link={{
              title: intl.formatMessage({ id: "See alternative hotels" }),
              url: `${alternativeHotels(lang)}`,
              keepSearchParams: true,
            }}
          />
        </div>
      ) : null}
      <RoomTypeFilter />
      {showBookingCodeFilter ? <BookingCodeFilter /> : null}
      <ul className={styles.roomList}>
        {visibleRooms.map((roomConfiguration) => (
          <RoomCard
            key={roomConfiguration.roomTypeCode}
            roomConfiguration={roomConfiguration}
          />
        ))}
      </ul>
    </>
  )
}
