"use client"

import { useCallback, useEffect, useRef } from "react"
import { useIntl } from "react-intl"
import { useMediaQuery } from "usehooks-ts"

import { useHotelsMapStore } from "@/stores/hotels-map"

import useClickOutside from "@/hooks/useClickOutside"

import HotelCardDialog from "../HotelCardDialog"
import { getHotelPins } from "./utils"

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

import type { HotelCardDialogListingProps } from "@/types/components/hotelReservation/selectHotel/map"

export default function HotelCardDialogListing({
  hotels,
}: HotelCardDialogListingProps) {
  const intl = useIntl()
  const isRedemption = hotels?.find((hotel) => hotel.price?.redemption)
  const currencyValue = isRedemption
    ? intl.formatMessage({ id: "Points" })
    : undefined
  const hotelsPinData = hotels ? getHotelPins(hotels, currencyValue) : []
  const activeCardRef = useRef<HTMLDivElement | null>(null)
  const observerRef = useRef<IntersectionObserver | null>(null)
  const dialogRef = useRef<HTMLDivElement>(null)
  const isMobile = useMediaQuery("(max-width: 768px)")
  const { activeHotelCard, setActiveHotelCard, setActiveHotelPin } =
    useHotelsMapStore()

  function handleClose() {
    setActiveHotelCard(null)
    setActiveHotelPin(null)
  }

  useClickOutside(dialogRef, !!activeHotelCard && isMobile, handleClose)

  const handleIntersection = useCallback(
    (entries: IntersectionObserverEntry[]) => {
      entries.forEach((entry) => {
        if (entry.isIntersecting) {
          const cardName = entry.target.getAttribute("data-name")
          if (cardName) {
            setActiveHotelCard(cardName)
          }
        }
      })
    },
    [setActiveHotelCard]
  )

  useEffect(() => {
    observerRef.current = new IntersectionObserver(handleIntersection, {
      root: null,
      threshold: 0.5,
    })

    const elements = document.querySelectorAll("[data-name]")
    elements.forEach((el) => observerRef.current?.observe(el))

    return () => {
      elements.forEach((el) => observerRef.current?.unobserve(el))
      observerRef.current?.disconnect()
    }
  }, [handleIntersection])

  useEffect(() => {
    if (activeCardRef.current) {
      // Temporarily disconnect the observer
      observerRef.current?.disconnect()

      activeCardRef.current.scrollIntoView({
        behavior: "smooth",
        block: "nearest",
        inline: "center",
      })

      // Reconnect the observer after scrolling
      const elements = document.querySelectorAll("[data-name]")
      setTimeout(() => {
        elements.forEach((el) => observerRef.current?.observe(el))
      }, 1000)
    }
  }, [activeHotelCard])

  return (
    <div className={styles.hotelCardDialogListing} ref={dialogRef}>
      {!!hotelsPinData?.length &&
        hotelsPinData.map((data) => {
          const isActive = data.name === activeHotelCard
          return (
            <div
              key={data.name}
              ref={isActive ? activeCardRef : null}
              data-name={data.name}
            >
              <HotelCardDialog
                data={data}
                isOpen={!!activeHotelCard}
                handleClose={handleClose}
                type="listing"
              />
            </div>
          )
        })}
    </div>
  )
}
