"use client"

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

import Caption from "@/components/TempDesignSystem/Text/Caption"
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
import { useRateSummary } from "@/hooks/selectRate/useRateSummary"
import { useRoomFiltering } from "@/hooks/selectRate/useRoomFiltering"
import { trackLowestRoomPrice } from "@/utils/tracking"
import { convertObjToSearchParams } from "@/utils/url"

import RateSummary from "../RateSummary"
import { RoomSelectionPanel } from "../RoomSelectionPanel"
import SelectedRoomPanel from "../SelectedRoomPanel"
import { filterDuplicateRoomTypesByLowestPrice, parseRoomParams } from "./utils"

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 {
  Rate,
  RateCode,
} from "@/types/components/hotelReservation/selectRate/selectRate"
import type { RoomConfiguration } from "@/server/routers/hotels/output"

type SelectedRates = (RateCode | undefined)[]

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

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

  const searchedRoomsAndGuests = useMemo(
    () => parseRoomParams(searchParams),
    [searchParams]
  )

  const [selectedRates, setSelectedRates] = useState<SelectedRates>(
    new Array(searchedRoomsAndGuests.length).fill(undefined)
  )

  const isMultipleRooms = searchedRoomsAndGuests.length > 1

  const intl = useIntl()

  const visibleRooms: RoomConfiguration[] = useMemo(() => {
    const deduped = filterDuplicateRoomTypesByLowestPrice(
      roomsAvailability.roomConfigurations
    )

    const separated = deduped.reduce<{
      available: RoomConfiguration[]
      notAvailable: RoomConfiguration[]
    }>(
      (acc, curr) => {
        if (curr.status === "NotAvailable") {
          return { ...acc, notAvailable: [...acc.notAvailable, curr] }
        }
        return { ...acc, available: [...acc.available, curr] }
      },
      { available: [], notAvailable: [] }
    )

    return [...separated.available, ...separated.notAvailable]
  }, [roomsAvailability.roomConfigurations])

  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 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]
  )

  const { selectedPackagesByRoom, getRooms, handleFilter, getFilteredRooms } =
    useRoomFiltering({ roomsAvailability })

  const rateSummary = useRateSummary({
    searchedRoomsAndGuests,
    selectedRates,
    getFilteredRooms,
    selectedPackagesByRoom,
    availablePackages,
    roomCategories,
  })

  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.replaceState(
      null,
      "",
      `${pathname}?${queryParams.toString()}`
    )
    router.push(`select-bed?${queryParams}`)
  }

  const setSelectedRateForRoom = useCallback(
    (index: number) => (value: React.SetStateAction<RateCode | undefined>) => {
      setSelectedRates((prev) => {
        const newRates = [...prev]
        newRates[index] =
          typeof value === "function" ? value(prev[index]) : value
        return newRates
      })
    },
    []
  )

  const handleFilterForRoom = useCallback(
    (index: number) =>
      (filter: Record<RoomPackageCodeEnum, boolean | undefined>) => {
        handleFilter(filter, index)
      },
    [handleFilter]
  )

  return (
    <div className={styles.content}>
      {isMultipleRooms ? (
        searchedRoomsAndGuests.map((room, index) => (
          <div key={index} className={styles.roomContainer}>
            {selectedRates[index] === undefined && (
              <Subtitle>
                {intl.formatMessage(
                  { id: "Room {roomIndex}" },
                  { roomIndex: index + 1 }
                )}
                ,{" "}
                {intl.formatMessage(
                  {
                    id: room.children?.length
                      ? "{adults} adults, {children} children"
                      : "{adults} adults",
                  },
                  {
                    adults: room.adults,
                    children: room.children?.length,
                  }
                )}
              </Subtitle>
            )}
            <div
              className={styles.roomSelectionPanelContainer}
              data-selected={selectedRates[index] !== undefined}
              data-active-panel={
                (index === 0 || selectedRates[index - 1] !== undefined) &&
                selectedRates[index] === undefined
              }
            >
              <div className={styles.selectedRoomPanel}>
                <SelectedRoomPanel
                  roomIndex={index}
                  room={room}
                  selectedRate={rateSummary[index]}
                  roomCategories={roomCategories}
                />
              </div>
              <div className={styles.roomSelectionPanel}>
                <RoomSelectionPanel
                  rooms={getRooms(index)}
                  roomCategories={roomCategories}
                  availablePackages={availablePackages}
                  selectedPackages={selectedPackagesByRoom[index]}
                  setSelectedRate={setSelectedRateForRoom(index)}
                  hotelType={hotelType}
                  handleFilter={handleFilterForRoom(index)}
                  defaultPackages={defaultPackages}
                  roomListIndex={index}
                />
              </div>
            </div>
          </div>
        ))
      ) : (
        <RoomSelectionPanel
          rooms={getRooms(0)}
          roomCategories={roomCategories}
          availablePackages={availablePackages}
          selectedPackages={selectedPackagesByRoom[0]}
          setSelectedRate={setSelectedRateForRoom(0)}
          hotelType={hotelType}
          handleFilter={handleFilterForRoom(0)}
          defaultPackages={defaultPackages}
          roomListIndex={0}
        />
      )}

      {rateSummary && (
        <form
          method="GET"
          action={`select-bed?${searchParams}`}
          onSubmit={handleSubmit}
        >
          <RateSummary
            rateSummary={rateSummary.filter(
              (summary): summary is Rate => summary !== null
            )}
            isUserLoggedIn={isUserLoggedIn}
            packages={availablePackages}
            roomsAvailability={roomsAvailability}
          />
        </form>
      )}
    </div>
  )
}
