"use client"
import { useMap } from "@vis.gl/react-google-maps"
import { useCallback, useEffect, useMemo, useRef, useState } from "react"
import { useIntl } from "react-intl"
import { useMediaQuery } from "usehooks-ts"

import { selectHotel } from "@/constants/routes/hotelReservation"
import { useHotelFilterStore } from "@/stores/hotel-filters"
import { useHotelsMapStore } from "@/stores/hotels-map"

import { RoomCardSkeleton } from "@/components/HotelReservation/RoomCardSkeleton/RoomCardSkeleton"
import { CloseIcon, CloseLargeIcon } from "@/components/Icons"
import InteractiveMap from "@/components/Maps/InteractiveMap"
import { BackToTopButton } from "@/components/TempDesignSystem/BackToTopButton"
import Button from "@/components/TempDesignSystem/Button"
import Link from "@/components/TempDesignSystem/Link"
import useLang from "@/hooks/useLang"
import { useScrollToTop } from "@/hooks/useScrollToTop"
import { debounce } from "@/utils/debounce"

import FilterAndSortModal from "../../FilterAndSortModal"
import HotelListing from "../HotelListing"
import { getVisibleHotels } from "./utils"

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

import type { HotelData } from "@/types/components/hotelReservation/selectHotel/hotelCardListingProps"
import type { SelectHotelMapProps } from "@/types/components/hotelReservation/selectHotel/map"

const SKELETON_LOAD_DELAY = 750

export default function SelectHotelContent({
  hotelPins,
  cityCoordinates,
  mapId,
  hotels,
  filterList,
}: Omit<SelectHotelMapProps, "apiKey">) {
  const lang = useLang()
  const intl = useIntl()
  const map = useMap()

  const isAboveMobile = useMediaQuery("(min-width: 768px)")
  const [visibleHotels, setVisibleHotels] = useState<HotelData[]>([])
  const [showSkeleton, setShowSkeleton] = useState<boolean>(true)
  const listingContainerRef = useRef<HTMLDivElement | null>(null)

  const activeFilters = useHotelFilterStore((state) => state.activeFilters)
  const { activeHotelCard, activeHotelPin } = useHotelsMapStore()

  const { showBackToTop, scrollToTop } = useScrollToTop({
    threshold: 490,
    elementRef: listingContainerRef,
  })

  const coordinates = useMemo(
    () =>
      isAboveMobile
        ? cityCoordinates
        : { ...cityCoordinates, lat: cityCoordinates.lat - 0.006 },
    [isAboveMobile, cityCoordinates]
  )

  useEffect(() => {
    if (listingContainerRef.current) {
      const activeElement =
        listingContainerRef.current.querySelector(`[data-active="true"]`)
      if (activeElement) {
        activeElement.scrollIntoView({ behavior: "smooth", block: "nearest" })
      }
    }
  }, [activeHotelCard, activeHotelPin])

  const filteredHotelPins = useMemo(
    () =>
      hotelPins.filter((hotel) =>
        activeFilters.every((filterId) =>
          hotel.facilityIds.includes(Number(filterId))
        )
      ),
    [activeFilters, hotelPins]
  )

  const getHotelCards = useCallback(() => {
    const visibleHotels = getVisibleHotels(hotels, filteredHotelPins, map)
    setVisibleHotels(visibleHotels)
    setTimeout(() => {
      setShowSkeleton(false)
    }, SKELETON_LOAD_DELAY)
  }, [hotels, filteredHotelPins, map])

  /**
   * Updates visible hotels when map viewport changes (zoom/pan)
   * - Debounces updates to prevent excessive re-renders during map interaction
   * - Shows loading skeleton while map tiles load
   * - Triggers on: initial load, zoom, pan, and tile loading completion
   */
  const debouncedUpdateHotelCards = useMemo(
    () =>
      debounce(() => {
        if (!map) return
        if (isAboveMobile) {
          setShowSkeleton(true)
        }
        getHotelCards()
      }, 100),
    [map, getHotelCards, isAboveMobile]
  )

  const closeButton = (
    <Button
      intent="inverted"
      size="small"
      theme="base"
      className={styles.closeButton}
      asChild
    >
      <Link href={selectHotel(lang)} keepSearchParams prefetch>
        <CloseIcon color="burgundy" />
        {intl.formatMessage({ id: "Close the map" })}
      </Link>
    </Button>
  )

  return (
    <div className={styles.container}>
      <div className={styles.listingContainer} ref={listingContainerRef}>
        <div className={styles.filterContainer}>
          <Button
            intent="text"
            size="small"
            variant="icon"
            wrapping
            className={styles.filterContainerCloseButton}
            asChild
          >
            <Link href={selectHotel(lang)} keepSearchParams>
              <CloseLargeIcon />
            </Link>
          </Button>
          <FilterAndSortModal
            filters={filterList}
            setShowSkeleton={setShowSkeleton}
          />
        </div>

        {showSkeleton ? (
          <div className={styles.skeletonContainer}>
            <RoomCardSkeleton />
            <RoomCardSkeleton />
          </div>
        ) : (
          <HotelListing hotels={visibleHotels} />
        )}
        {showBackToTop && (
          <BackToTopButton position="left" onClick={scrollToTop} />
        )}
      </div>
      <InteractiveMap
        closeButton={closeButton}
        coordinates={coordinates}
        hotelPins={filteredHotelPins}
        mapId={mapId}
        onTilesLoaded={debouncedUpdateHotelCards}
      />
    </div>
  )
}
