"use client"

import { useMap } from "@vis.gl/react-google-maps"
import { useEffect } from "react"

import { useDestinationPageHotelsMapStore } from "@/stores/destination-page-hotels-map"

import { useSupercluster } from "@/hooks/maps/use-supercluster"

import ClusterMarker from "./ClusterMarker"
import Marker from "./Marker"

import type { ClusterProperties } from "supercluster"

import type {
  MarkerGeojson,
  MarkerProperties,
} from "@/types/components/maps/destinationMarkers"

interface MapContentProps {
  geojson: MarkerGeojson
  disableClustering?: boolean
}

// Important this is outside the component to avoid re-creating the object on each render
// which is making the useSupercluster hook fail
// Options are defined according to the supercluster documentation: https://github.com/mapbox/supercluster/blob/main/README.md#options
const CLUSTER_OPTIONS = {
  maxZoom: 14,
  extent: 256,
}

export default function MapContent({
  geojson,
  disableClustering,
}: MapContentProps) {
  const { setActiveMarker, activeMarker } = useDestinationPageHotelsMapStore()
  const map = useMap()

  const { clusters, containedHotels, getClusterZoom } =
    useSupercluster<MarkerProperties>(geojson, CLUSTER_OPTIONS)

  // Based on the length of active filters, we decide if should show clusters or individual markers
  const markerList = disableClustering ? geojson.features : clusters

  useEffect(() => {
    map?.addListener("click", () => {
      if (activeMarker) {
        setActiveMarker(null)
      }
    })
  }, [activeMarker, map, setActiveMarker])

  function handleClusterClick(
    position: google.maps.LatLngLiteral,
    clusterProperties: ClusterProperties
  ) {
    const currentZoom = map && map.getZoom()
    const clusterZoom = getClusterZoom(clusterProperties.cluster_id)

    if (currentZoom) {
      map.panTo(position)
      map.setZoom(clusterZoom ?? currentZoom + 2)
    }
  }

  return markerList.map((feature, idx) => {
    const [lng, lat] = feature.geometry.coordinates
    const clusterProperties = feature.properties as ClusterProperties
    const markerProperties = feature.properties as MarkerProperties
    const isCluster = clusterProperties?.cluster

    return isCluster ? (
      <ClusterMarker
        key={feature.id}
        position={{ lat, lng }}
        size={clusterProperties.point_count}
        sizeAsText={String(clusterProperties.point_count_abbreviated)}
        onMarkerClick={(position) =>
          handleClusterClick(position, clusterProperties)
        }
        hotelIds={containedHotels[idx]}
      />
    ) : (
      <Marker
        key={feature.id}
        position={{ lat, lng }}
        properties={markerProperties}
      />
    )
  })
}
