"use client"
import { usePathname, useRouter, useSearchParams } from "next/navigation"
import { useSession } from "next-auth/react"
import { useCallback, useEffect, useMemo, useRef } from "react"

import { debounce } from "@/utils/debounce"
import { isValidSession } from "@/utils/session"

import RateSummary from "./RateSummary"
import RoomCard from "./RoomCard"
import {
  getHotelReservationQueryParams,
  RATE_CARD_EQUAL_HEIGHT_CLASS,
  RATE_CARDS_AVAILABLE_HEIGHT_CLASS,
  RATE_CARDS_NOT_AVAILABLE_HEIGHT_CLASS,
} from "./utils"

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

import type { RoomSelectionProps } from "@/types/components/hotelReservation/selectRate/roomSelection"

export default function RoomSelection({
  roomsAvailability,
  roomCategories,
  availablePackages,
  selectedPackages,
  setRateCode,
  rateSummary,
  hotelType,
}: RoomSelectionProps) {
  const router = useRouter()
  const pathname = usePathname()
  const searchParams = useSearchParams()
  const session = useSession()
  const isUserLoggedIn = isValidSession(session.data)
  const roomRefs = useRef<HTMLLIElement[]>([])
  const { roomConfigurations, rateDefinitions } = roomsAvailability

  const equalizePriceOptionHeights = useCallback(() => {
    if (!roomRefs.current.length) return

    const optionsSelector = `.${RATE_CARD_EQUAL_HEIGHT_CLASS}`
    const availableSelector = `.${RATE_CARDS_AVAILABLE_HEIGHT_CLASS}`
    const notAvailableSelector = `.${RATE_CARDS_NOT_AVAILABLE_HEIGHT_CLASS}`
    const DEFAULT_RATE_CARD_HEIGHT = 380

    const maxOptionHeights: number[] = []
    let maxPriceCardHeight = DEFAULT_RATE_CARD_HEIGHT

    roomRefs.current.forEach((room) => {
      const options = room.querySelectorAll<HTMLDivElement>(optionsSelector)
      options.forEach((option, i) => {
        option.style.height = "auto"
        const optionHeight = option.getBoundingClientRect().height
        maxOptionHeights[i] = Math.max(maxOptionHeights[i] || 0, optionHeight)
      })

      const priceCard = room.querySelector(availableSelector) as HTMLElement
      if (priceCard) {
        const priceCardHeight = priceCard.getBoundingClientRect().height
        maxPriceCardHeight = Math.max(maxPriceCardHeight, priceCardHeight)
      }
    })

    roomRefs.current.forEach((room) => {
      const options = room.querySelectorAll<HTMLDivElement>(optionsSelector)
      options.forEach((option, i) => {
        if (option) {
          option.style.height = `${maxOptionHeights[i]}px`
        }
      })

      const noPriceCard = room.querySelector(
        notAvailableSelector
      ) as HTMLElement
      if (noPriceCard) {
        noPriceCard.style.height = `${maxPriceCardHeight}px`
      }
    })
  }, [])

  useEffect(() => {
    const debouncedResizeHandler = debounce(function () {
      equalizePriceOptionHeights()
    })

    const observer = new ResizeObserver(debouncedResizeHandler)

    observer.observe(document.documentElement)

    return () => {
      if (observer) {
        observer.unobserve(document.documentElement)
      }
    }
  }, [roomRefs, equalizePriceOptionHeights])

  const queryParams = useMemo(() => {
    const params = new URLSearchParams(searchParams)
    const searchParamsObject = getHotelReservationQueryParams(searchParams)

    searchParamsObject.room.forEach((item, index) => {
      if (rateSummary?.roomTypeCode) {
        params.set(`room[${index}].roomtype`, rateSummary.roomTypeCode)
      }
      if (rateSummary?.public?.rateCode) {
        params.set(`room[${index}].ratecode`, rateSummary.public.rateCode)
      }
      if (rateSummary?.member?.rateCode) {
        params.set(
          `room[${index}].counterratecode`,
          rateSummary.member.rateCode
        )
      }
      selectedPackages.length > 0
        ? params.set(`room[${index}].packages`, selectedPackages.join(","))
        : params.delete(`room[${index}].packages`)
    })

    return params
  }, [searchParams, rateSummary, selectedPackages])

  function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
    e.preventDefault()

    window.history.replaceState(
      null,
      "",
      `${pathname}?${queryParams.toString()}`
    )
    router.push(`select-bed?${queryParams}`)
  }

  return (
    <div className={styles.wrapper}>
      <form
        method="GET"
        action={`select-bed?${searchParams}`}
        onSubmit={handleSubmit}
      >
        <ul className={styles.roomList}>
          {roomConfigurations.map((roomConfiguration, index) => (
            <li
              key={roomConfiguration.roomTypeCode}
              ref={(el) => {
                if (el) roomRefs.current[index] = el
              }}
            >
              <RoomCard
                hotelId={roomsAvailability.hotelId.toString()}
                hotelType={hotelType}
                rateDefinitions={rateDefinitions}
                roomConfiguration={roomConfiguration}
                roomCategories={roomCategories}
                handleSelectRate={setRateCode}
                selectedPackages={selectedPackages}
                packages={availablePackages}
              />
            </li>
          ))}
        </ul>
        {rateSummary && (
          <RateSummary
            rateSummary={rateSummary}
            isUserLoggedIn={isUserLoggedIn}
            packages={availablePackages}
            roomsAvailability={roomsAvailability}
          />
        )}
      </form>
    </div>
  )
}
