"use client"
import { APIProvider } from "@vis.gl/react-google-maps"
import { useCallback, useEffect, useRef, useState } from "react"
import { Dialog, Modal } from "react-aria-components"
import { useIntl } from "react-intl"

import useHotelPageStore from "@/stores/hotel-page"

import CloseLargeIcon from "@/components/Icons/CloseLarge"
import InteractiveMap from "@/components/Maps/InteractiveMap"
import Button from "@/components/TempDesignSystem/Button"
import { useHandleKeyUp } from "@/hooks/useHandleKeyUp"
import { debounce } from "@/utils/debounce"

import Sidebar from "./Sidebar"

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

import type { DynamicMapProps } from "@/types/components/hotelPage/map/dynamicMap"

export default function DynamicMap({
  apiKey,
  hotelName,
  coordinates,
  pointsOfInterest,
  mapId,
}: DynamicMapProps) {
  const intl = useIntl()
  const rootDiv = useRef<HTMLDivElement | null>(null)
  const [mapHeight, setMapHeight] = useState("0px")
  const { isDynamicMapOpen, closeDynamicMap } = useHotelPageStore()
  const [scrollHeightWhenOpened, setScrollHeightWhenOpened] = useState(0)
  const [activePoi, setActivePoi] = useState<string | null>(null)

  useHandleKeyUp((event: KeyboardEvent) => {
    if (event.key === "Escape" && isDynamicMapOpen) {
      closeDynamicMap()
    }
  })

  // Calculate the height of the map based on the viewport height from the start-point (below the header and booking widget)
  const handleMapHeight = useCallback(() => {
    const topPosition = rootDiv.current?.getBoundingClientRect().top ?? 0
    const scrollY = window.scrollY
    setMapHeight(`calc(100dvh - ${topPosition + scrollY}px)`)
  }, [])

  // Making sure the map is always opened at the top of the page,
  // just below the header and booking widget as these should stay visible.
  // When closing, the page should scroll back to the position it was before opening the map.
  useEffect(() => {
    // Skip the first render
    if (!rootDiv.current) {
      return
    }

    if (isDynamicMapOpen && scrollHeightWhenOpened === 0) {
      const scrollY = window.scrollY
      setScrollHeightWhenOpened(scrollY)
      window.scrollTo({ top: 0, behavior: "instant" })
    } else if (!isDynamicMapOpen && scrollHeightWhenOpened !== 0) {
      window.scrollTo({ top: scrollHeightWhenOpened, behavior: "instant" })
      setScrollHeightWhenOpened(0)
    }
  }, [isDynamicMapOpen, scrollHeightWhenOpened, rootDiv])

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

    const observer = new ResizeObserver(debouncedResizeHandler)

    observer.observe(document.documentElement)

    return () => {
      if (observer) {
        observer.unobserve(document.documentElement)
      }
    }
  }, [rootDiv, isDynamicMapOpen, handleMapHeight])

  const closeButton = (
    <Button
      theme="base"
      intent="inverted"
      variant="icon"
      size="small"
      className={styles.closeButton}
      onClick={closeDynamicMap}
    >
      <CloseLargeIcon color="burgundy" />
      <span>{intl.formatMessage({ id: "Close the map" })}</span>
    </Button>
  )

  return (
    <APIProvider apiKey={apiKey}>
      <div className={styles.wrapper} ref={rootDiv}>
        <Modal
          isOpen={isDynamicMapOpen}
          UNSTABLE_portalContainer={rootDiv.current || undefined}
        >
          <Dialog
            className={styles.dynamicMap}
            style={{ "--hotel-map-height": mapHeight } as React.CSSProperties}
            aria-label={intl.formatMessage(
              { id: "Things nearby HOTEL_NAME" },
              { hotelName }
            )}
          >
            <Sidebar
              activePoi={activePoi}
              hotelName={hotelName}
              pointsOfInterest={pointsOfInterest}
              onActivePoiChange={setActivePoi}
              coordinates={coordinates}
            />
            <InteractiveMap
              closeButton={closeButton}
              coordinates={coordinates}
              pointsOfInterest={pointsOfInterest}
              activePoi={activePoi}
              onActivePoiChange={setActivePoi}
              mapId={mapId}
            />
          </Dialog>
        </Modal>
      </div>
    </APIProvider>
  )
}
