"use client"

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

import { useRateSelectionStore } from "@/stores/select-rate/rate-selection"
import { useRoomFilteringStore } from "@/stores/select-rate/room-filtering"

import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
import { trackLowestRoomPrice } from "@/utils/tracking"
import { convertObjToSearchParams, convertSearchParamsToObj } from "@/utils/url"

import RateSummary from "../RateSummary"
import { RoomSelectionPanel } from "../RoomSelectionPanel"
import SelectedRoomPanel from "../SelectedRoomPanel"
import { roomSelectionPanelVariants } from "./variants"

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

import {
  type DefaultFilterOptions,
  RoomPackageCodeEnum,
} from "@/types/components/hotelReservation/selectRate/roomFilter"
import type { SelectRateProps } from "@/types/components/hotelReservation/selectRate/roomSelection"
import type { SelectRateSearchParams } from "@/types/components/hotelReservation/selectRate/selectRate"

export default function Rooms({
  availablePackages,
  hotelType,
  isUserLoggedIn,
  roomsAvailability,
  roomCategories = [],
  vat,
}: SelectRateProps) {
  const router = useRouter()
  const pathname = usePathname()
  const searchParams = useSearchParams()
  const intl = useIntl()

  const hotelId = searchParams.get("hotel")
  const arrivalDate = searchParams.get("fromDate")
  const departureDate = searchParams.get("toDate")

  const {
    selectedRates,
    rateSummary,
    calculateRateSummary,
    initializeRates,
    setGuestsInRooms,
  } = useRateSelectionStore()

  const {
    selectedPackagesByRoom,
    visibleRooms,
    setVisibleRooms,
    setRoomsAvailability,
    getFilteredRooms,
  } = useRoomFilteringStore()

  const bookingWidgetSearchData = useMemo(
    () =>
      convertSearchParamsToObj<SelectRateSearchParams>(
        Object.fromEntries(searchParams)
      ),
    [searchParams]
  )

  useEffect(() => {
    bookingWidgetSearchData.rooms.forEach((room, index) => {
      setGuestsInRooms(index, room.adults, room.childrenInRoom)
    })
  }, [bookingWidgetSearchData.rooms, setGuestsInRooms])

  const isMultipleRooms = bookingWidgetSearchData.rooms.length > 1

  useEffect(() => {
    initializeRates(bookingWidgetSearchData.rooms.length)
  }, [initializeRates, bookingWidgetSearchData.rooms.length])

  const defaultPackages: DefaultFilterOptions[] = useMemo(
    () => [
      {
        code: RoomPackageCodeEnum.ACCESSIBILITY_ROOM,
        description: intl.formatMessage({ id: "Accessible room" }),
        itemCode: availablePackages.find(
          (pkg) => pkg.code === RoomPackageCodeEnum.ACCESSIBILITY_ROOM
        )?.itemCode,
      },
      {
        code: RoomPackageCodeEnum.ALLERGY_ROOM,
        description: intl.formatMessage({ id: "Allergy-friendly room" }),
        itemCode: availablePackages.find(
          (pkg) => pkg.code === RoomPackageCodeEnum.ALLERGY_ROOM
        )?.itemCode,
      },
      {
        code: RoomPackageCodeEnum.PET_ROOM,
        description: intl.formatMessage({ id: "Pet room" }),
        itemCode: availablePackages.find(
          (pkg) => pkg.code === RoomPackageCodeEnum.PET_ROOM
        )?.itemCode,
      },
    ],
    [availablePackages, intl]
  )

  useEffect(() => {
    if (roomsAvailability) {
      setRoomsAvailability(roomsAvailability)
    }
    setVisibleRooms()
  }, [roomsAvailability, setRoomsAvailability, setVisibleRooms])

  useEffect(() => {
    if (
      selectedRates.length > 0 &&
      selectedRates.some((rate) => rate !== undefined)
    ) {
      calculateRateSummary({
        getFilteredRooms,
        availablePackages,
        roomCategories,
        selectedPackagesByRoom,
      })
    }
  }, [
    selectedRates,
    getFilteredRooms,
    availablePackages,
    roomCategories,
    selectedPackagesByRoom,
    calculateRateSummary,
  ])

  useEffect(() => {
    if (!rateSummary?.some((rate) => rate === null)) return

    const hasAnySelection = selectedRates.some((rate) => rate !== undefined)
    if (!hasAnySelection) return
  }, [rateSummary, selectedRates])

  useEffect(() => {
    const pricesWithCurrencies = visibleRooms.flatMap((room) =>
      room.products.map((product) => ({
        price: product.productType.public.localPrice.pricePerNight,
        currency: product.productType.public.localPrice.currency,
      }))
    )
    const lowestPrice = pricesWithCurrencies.reduce(
      (minPrice, { price }) => Math.min(minPrice, price),
      Infinity
    )

    const currency = pricesWithCurrencies[0]?.currency

    trackLowestRoomPrice({
      hotelId,
      arrivalDate,
      departureDate,
      lowestPrice: lowestPrice,
      currency: currency,
    })
  }, [arrivalDate, departureDate, hotelId, visibleRooms])

  const queryParams = useMemo(() => {
    const rooms = rateSummary.map((rate, index) => ({
      roomTypeCode: rate?.roomTypeCode,
      rateCode: rate?.public.rateCode,
      counterRateCode: rate?.member?.rateCode,
      packages: selectedPackagesByRoom[index] || [],
    }))

    const newSearchParams = convertObjToSearchParams({ rooms }, searchParams)

    return newSearchParams
  }, [searchParams, rateSummary, selectedPackagesByRoom])

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

    window.history.pushState(null, "", `${pathname}?${queryParams.toString()}`)
    router.push(`details?${queryParams}`)
  }

  useEffect(() => {
    requestAnimationFrame(() => {
      const SCROLL_OFFSET = 100
      const roomElements = document.querySelectorAll(`.${styles.roomContainer}`)
      const index = selectedRates.findIndex((rate) => rate === undefined)

      const targetIndex = index === -1 ? selectedRates.length - 1 : index - 1
      const selectedRoom = roomElements[targetIndex]

      if (selectedRoom) {
        const elementPosition = selectedRoom.getBoundingClientRect().top
        const offsetPosition = elementPosition + window.scrollY - SCROLL_OFFSET

        window.scrollTo({
          top: offsetPosition,
          behavior: "smooth",
        })
      }
    })
  }, [selectedRates])

  return (
    <div className={styles.content}>
      {isMultipleRooms ? (
        bookingWidgetSearchData.rooms.map((room, index) => {
          const classNames = roomSelectionPanelVariants({
            active:
              (index === 0 || selectedRates[index - 1] !== undefined) &&
              selectedRates[index] === undefined,
            selected: selectedRates[index] !== undefined,
          })
          return (
            <div key={index} className={styles.roomContainer}>
              {selectedRates[index] === undefined && (
                <Subtitle>
                  {intl.formatMessage(
                    { id: "Room {roomIndex}" },
                    { roomIndex: index + 1 }
                  )}
                  ,{" "}
                  {intl.formatMessage(
                    {
                      id: room.childrenInRoom?.length
                        ? "{adults} adults, {children} children"
                        : "{adults} adults",
                    },
                    {
                      adults: room.adults,
                      children: room.childrenInRoom?.length,
                    }
                  )}
                </Subtitle>
              )}
              <div className={classNames}>
                <div className={styles.roomPanel}>
                  <SelectedRoomPanel
                    roomIndex={index}
                    room={room}
                    roomCategories={roomCategories}
                  />
                </div>
                <div className={styles.roomSelectionPanel}>
                  <RoomSelectionPanel
                    availablePackages={availablePackages}
                    defaultPackages={defaultPackages}
                    hotelType={hotelType}
                    roomCategories={roomCategories}
                    roomListIndex={index}
                    selectedPackages={selectedPackagesByRoom[index]}
                  />
                </div>
              </div>
            </div>
          )
        })
      ) : (
        <RoomSelectionPanel
          availablePackages={availablePackages}
          defaultPackages={defaultPackages}
          hotelType={hotelType}
          roomCategories={roomCategories}
          roomListIndex={0}
          selectedPackages={selectedPackagesByRoom[0]}
        />
      )}

      {rateSummary && roomsAvailability && (
        <form
          method="GET"
          action={`details?${searchParams}`}
          onSubmit={handleSubmit}
        >
          <RateSummary
            isUserLoggedIn={isUserLoggedIn}
            packages={availablePackages}
            roomsAvailability={roomsAvailability}
            booking={bookingWidgetSearchData}
            vat={vat}
          />
        </form>
      )}
    </div>
  )
}
