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

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

import BookingCodeFilter from "@/components/HotelReservation/SelectHotel/BookingCodeFilter"
import Alert from "@/components/TempDesignSystem/Alert"
import { useRoomContext } from "@/contexts/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"
import type { RoomConfiguration } from "@/types/trpc/routers/hotel/roomAvailability"

export default function RoomSelectionPanel() {
  const { rooms } = useRoomContext()
  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
  )

  // With Booking code rates we will always obtain public rate and never a member rate,
  // so we should ignore it from the logic below.
  const isRegularRatesAvailableWithCode =
    bookingCode &&
    rooms.some(
      (room) =>
        room.status === AvailabilityEnum.Available &&
        room.products.some(
          (product) =>
            product.productType.public.rateType === RateTypeEnum.Regular
        )
    )

  // Booking codes rate comes with various rate types but Regular is reserved
  // for non-booking code rates (Save, Change & Flex)
  const isBookingCodeRatesAvailable =
    bookingCode &&
    rooms.some(
      (room) =>
        room.status === AvailabilityEnum.Available &&
        room.products.some(
          (product) =>
            product.productType.public.rateType !== RateTypeEnum.Regular
        )
    )

  // Show all rooms if either booking code rates or regular rates are not available
  // or filter selection is All rooms
  const showAllRooms =
    !isBookingCodeRatesAvailable ||
    !isRegularRatesAvailableWithCode ||
    activeCodeFilter === BookingCodeFilterEnum.All
  const bookingCodeDiscountedRooms = rooms.filter(
    (room) =>
      room.status === AvailabilityEnum.Available &&
      room.products.every(
        (product) =>
          product.productType.public.rateType !== RateTypeEnum.Regular
      )
  )
  const regularRateRooms = rooms.filter(
    (room) =>
      room.status === AvailabilityEnum.Available &&
      room.products.every(
        (product) =>
          product.productType.public.rateType === RateTypeEnum.Regular
      )
  )
  // Show booking code filter when both of the booking code rates or regular rates are available
  const showBookingCodeFilter =
    isRegularRatesAvailableWithCode && isBookingCodeRatesAvailable

  return (
    <>
      {noAvailableRooms || (bookingCode && !isBookingCodeRatesAvailable) ? (
        <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}>
        {/* Show either Booking code filtered rooms or all the rooms */}
        {showAllRooms
          ? rooms.map((roomConfiguration) => RoomCardWrap(roomConfiguration))
          : activeCodeFilter === BookingCodeFilterEnum.Discounted
            ? bookingCodeDiscountedRooms.map((roomConfiguration) =>
                RoomCardWrap(roomConfiguration)
              )
            : regularRateRooms.map((roomConfiguration) =>
                RoomCardWrap(roomConfiguration)
              )}
      </ul>
    </>
  )
}

function RoomCardWrap(roomConfiguration: RoomConfiguration) {
  return (
    <RoomCard
      key={roomConfiguration.roomTypeCode}
      roomConfiguration={roomConfiguration}
    />
  )
}
