"use client"

import { useRouter } from "next/navigation"
import { useCallback, useEffect, useRef, useState } from "react"
import { Dialog, Modal } from "react-aria-components"

import { debounce } from "@/utils/debounce"

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

export function MapModal({ children }: { children: React.ReactNode }) {
  const router = useRouter()
  const [mapHeight, setMapHeight] = useState("0px")
  const [mapTop, setMapTop] = useState("0px")
  const [isOpen, setIsOpen] = useState(true)
  const [scrollHeightWhenOpened, setScrollHeightWhenOpened] = useState(0)

  const rootDiv = useRef<HTMLDivElement | null>(null)

  const handleOnOpenChange = (open: boolean) => {
    setIsOpen(open)
    if (!open) {
      router.back()
    }
  }

  // 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)`)
    setMapTop(`${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 (scrollHeightWhenOpened === 0) {
      const scrollY = window.scrollY
      setScrollHeightWhenOpened(scrollY)
      window.scrollTo({ top: 0, behavior: "instant" })
    }
  }, [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, handleMapHeight])

  return (
    <div className={styles.wrapper} ref={rootDiv}>
      <Modal isDismissable isOpen={isOpen} onOpenChange={handleOnOpenChange}>
        <Dialog
          style={
            {
              "--hotel-map-height": mapHeight,
              "--hotel-map-top": mapTop,
            } as React.CSSProperties
          }
          className={styles.dynamicMap}
        >
          {children}
        </Dialog>
      </Modal>
    </div>
  )
}
