"use client"
import { useEffect } from "react"

import { REDEMPTION } from "@/constants/booking"
import { trpc } from "@/lib/trpc/client"
import { useRatesStore } from "@/stores/select-rate"

import { RoomContext } from "@/contexts/SelectRate/Room"
import useLang from "@/hooks/useLang"

import { BookingCodeFilterEnum } from "@/types/enums/bookingCodeFilter"
import { RateTypeEnum } from "@/types/enums/rateType"
import type { RoomProviderProps } from "@/types/providers/select-rate/room"

export default function RoomProvider({
  children,
  idx,
  room,
}: RoomProviderProps) {
  const lang = useLang()
  const {
    activeRoom,
    booking,
    roomAvailability,
    searchParams,
    selectedFilter,
    selectedPackages,
  } = useRatesStore((state) => ({
    activeRoom: state.activeRoom,
    booking: state.booking,
    roomAvailability: state.roomsAvailability?.[idx],
    searchParams: state.searchParams,
    selectedFilter: state.rooms[idx].selectedFilter,
    selectedPackages: state.rooms[idx].selectedPackages,
  }))
  const { appendRegularRates, addRoomFeatures, ...actions } = room.actions
  const roomNr = idx + 1

  const redemptionSearch = searchParams.has("searchType")
    ? searchParams.get("searchType") === REDEMPTION
    : false
  const hasRedemptionRates =
    redemptionSearch || room.rooms.some((room) => room.redemptions.length)
  const hasCorporateChequeOrVoucherRates = room.rooms.some((room) =>
    room.code.some((product) => {
      if ("corporateCheque" in product) {
        return product.corporateCheque.rateType === RateTypeEnum.CorporateCheque
      } else if ("voucher" in product) {
        return product.voucher.rateType === RateTypeEnum.Voucher
      }
      return false
    })
  )

  const dontShowRegularRates =
    hasRedemptionRates || hasCorporateChequeOrVoucherRates

  // Since input would be the same on single room as already
  // done in useRoomsAvailability hook, data is already present
  // and thus runs the appendRegularRates updater resulting in
  // duplicate data
  const enabled = !!(
    booking.bookingCode &&
    selectedFilter !== BookingCodeFilterEnum.Discounted &&
    !dontShowRegularRates
  )
  // Extra query needed to fetch regular rates upon user
  // selecting to view all rates.
  // TODO: Setup route to handle singular availability call
  const { data, isFetched, isFetching } =
    trpc.hotel.availability.roomsCombinedAvailability.useQuery(
      {
        adultsCount: [room.bookingRoom.adults],
        childArray: room.bookingRoom.childrenInRoom
          ? [room.bookingRoom.childrenInRoom]
          : undefined,
        hotelId: booking.hotelId,
        lang,
        roomStayEndDate: booking.toDate,
        roomStayStartDate: booking.fromDate,
      },
      {
        enabled,
      }
    )

  useEffect(() => {
    if (isFetched && !isFetching && data?.length && enabled) {
      const regularRates = data[0]
      if ("roomConfigurations" in regularRates) {
        appendRegularRates(regularRates.roomConfigurations)
      }
    }
  }, [appendRegularRates, data, enabled, isFetched, isFetching])

  const {
    data: roomFeaturesData,
    isFetched: isRoomFeaturesFetched,
    isFetching: isRoomFeaturesFetching,
  } = trpc.hotel.availability.roomFeatures.useQuery(
    {
      adults: room.bookingRoom.adults,
      childrenInRoom: room.bookingRoom.childrenInRoom,
      hotelId: booking.hotelId,
      startDate: booking.fromDate,
      endDate: booking.toDate,
      roomFeatureCodes: selectedPackages,
      roomIndex: idx, // Creates a unique query key for each room
    },
    {
      enabled: !!selectedPackages.length,
    }
  )

  useEffect(() => {
    if (
      isRoomFeaturesFetched &&
      !isRoomFeaturesFetching &&
      roomFeaturesData?.length
    ) {
      addRoomFeatures(roomFeaturesData)
    }
  }, [
    addRoomFeatures,
    roomFeaturesData,
    isRoomFeaturesFetched,
    isRoomFeaturesFetching,
  ])

  return (
    <RoomContext.Provider
      value={{
        ...room,
        actions,
        isActiveRoom: activeRoom === idx,
        isFetchingAdditionalRate: isFetched ? false : isFetching,
        isFetchingRoomFeatures: isRoomFeaturesFetched
          ? false
          : isRoomFeaturesFetching,
        isMainRoom: roomNr === 1,
        roomAvailability,
        roomNr,
        totalRooms: room.rooms.length,
      }}
    >
      {children}
    </RoomContext.Provider>
  )
}
