"use client"
import { APIProvider } from "@vis.gl/react-google-maps"
import { useRouter } from "next/navigation"
import {
  useCallback,
  useEffect,
  useLayoutEffect,
  useRef,
  useState,
} from "react"
import { useIntl } from "react-intl"

import { Button } from "@scandic-hotels/design-system/Button"
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"

import InteractiveMap from "@/components/Maps/InteractiveMap"
import { debounce } from "@/utils/debounce"

import Sidebar from "./Sidebar"

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

import type { Coordinates } from "@/types/components/maps/coordinates"
import type { MarkerInfo } from "@/types/components/maps/marker"
import type { PointOfInterest } from "@/types/hotel"

interface HotelMapPageClientProps {
  apiKey: string
  hotelName: string
  coordinates: Coordinates
  pointsOfInterest: PointOfInterest[]
  mapId: string
  markerInfo: MarkerInfo
}

export default function HotelMapPageClient({
  apiKey,
  hotelName,
  markerInfo,
  coordinates,
  pointsOfInterest,
  mapId,
}: HotelMapPageClientProps) {
  const intl = useIntl()
  const router = useRouter()
  const rootDiv = useRef<HTMLDivElement | null>(null)
  const [mapHeight, setMapHeight] = useState("100dvh")
  const [activePoi, setActivePoi] = useState<string | null>(null)

  // 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
    setMapHeight(`calc(100dvh - ${topPosition}px)`)
  }, [])

  function handleClose() {
    const url = new URL(window.location.href)
    url.searchParams.delete("view")
    router.push(url.toString())
  }

  useLayoutEffect(() => {
    const originalOverflowY = document.body.style.overflowY

    document.body.style.overflowY = "hidden"

    // 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.
    // Reason for this is that we're using the hash property on pages which we preserve
    // when navigating between pages.
    window.scrollTo({ top: 0, behavior: "instant" })

    return () => {
      document.body.style.overflowY = originalOverflowY
    }
  }, [])

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

    const observer = new ResizeObserver(debouncedResizeHandler)

    observer.observe(document.documentElement)

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

  const closeButton = (
    <Button
      variant="Primary"
      color="Inverted"
      size="Small"
      className={styles.closeButton}
      onPress={handleClose}
      typography="Body/Supporting text (caption)/smBold"
    >
      <MaterialIcon icon="close" size={20} color="CurrentColor" />
      <span>
        {intl.formatMessage({
          defaultMessage: "Close the map",
        })}
      </span>
    </Button>
  )

  return (
    <APIProvider apiKey={apiKey}>
      <div
        className={styles.mapWrapper}
        ref={rootDiv}
        style={{ "--hotel-map-height": mapHeight } as React.CSSProperties}
      >
        <Sidebar
          activePoi={activePoi}
          hotelName={hotelName}
          pointsOfInterest={pointsOfInterest}
          onActivePoiChange={(poi) => setActivePoi(poi ?? null)}
          coordinates={coordinates}
        />
        <InteractiveMap
          closeButton={closeButton}
          coordinates={coordinates}
          pointsOfInterest={pointsOfInterest}
          activePoi={activePoi}
          onActivePoiChange={(poi) => setActivePoi(poi ?? null)}
          mapId={mapId}
          markerInfo={markerInfo}
        />
      </div>
    </APIProvider>
  )
}
