"use client"

import { useEffect, useCallback } from "react"

import mapboxgl from "mapbox-gl"
import type { GeoJSON } from "geojson"
import type { IClusterLayerProps } from "@/app/_utils/types/map"
import { extractCrimeIncidents } from "@/app/_utils/map"

interface ExtendedClusterLayerProps extends IClusterLayerProps {
  clusteringEnabled?: boolean
  showClusters?: boolean
  sourceType?: string
}

export default function ClusterLayer({
  visible = true,
  map,
  crimes = [],
  filterCategory = "all",
  focusedDistrictId,
  clusteringEnabled = false,
  showClusters = false,
  sourceType = "cbt",
}: ExtendedClusterLayerProps) {
  const handleClusterClick = useCallback(
    (e: any) => {
      if (!map) return

      // Stop event propagation to prevent district layer from handling this click
      e.originalEvent.stopPropagation()
      e.preventDefault()

      const features = map.queryRenderedFeatures(e.point, { layers: ["clusters"] })

      if (!features || features.length === 0) return

      const clusterId: number = features[0].properties?.cluster_id as number

      try {
        ; (map.getSource("crime-incidents") as mapboxgl.GeoJSONSource).getClusterExpansionZoom(
          clusterId,
          (err, zoom) => {
            if (err) {
              console.error("Error getting cluster expansion zoom:", err)
              return
            }

            const coordinates = (features[0].geometry as any).coordinates

            map.flyTo({
              center: coordinates,
              zoom: zoom ?? 12,
              bearing: 0,
              pitch: 45,
              duration: 1000,
            })
          },
        )
      } catch (error) {
        console.error("Error handling cluster click:", error)
      }
    },
    [map],
  )

  useEffect(() => {
    if (!map || !visible) return

    const onStyleLoad = () => {
      if (!map) return

      try {
        const layers = map.getStyle().layers
        let firstSymbolId: string | undefined
        for (const layer of layers) {
          if (layer.type === "symbol") {
            firstSymbolId = layer.id
            break
          }
        }

        if (!map.getSource("crime-incidents")) {
          let features: GeoJSON.Feature[] = []

          if (sourceType === "cbu") {
            features = crimes.map(crime => ({
              type: "Feature",
              properties: {
                district_id: crime.district_id,
                district_name: crime.districts ? crime.districts.name : "Unknown",
                crime_count: crime.number_of_crime || 0,
                level: crime.level,
                category: filterCategory !== "all" ? filterCategory : "All",
                year: crime.year,
                month: crime.month,
                isCBU: true,
              },
              geometry: {
                type: "Point",
                coordinates: [
                  crime.districts?.geographics?.[0]?.longitude || 0,
                  crime.districts?.geographics?.[0]?.latitude || 0,
                ],
              },
            })) as GeoJSON.Feature[]
          } else {
            features = extractCrimeIncidents(crimes, filterCategory).filter(Boolean) as GeoJSON.Feature[]
          }

          map.addSource("crime-incidents", {
            type: "geojson",
            data: {
              type: "FeatureCollection",
              features: features,
            },
            cluster: clusteringEnabled,
            clusterMaxZoom: 14,
            clusterRadius: 50,
          })

          if (!map.getLayer("clusters")) {
            map.addLayer(
              {
                id: "clusters",
                type: "circle",
                source: "crime-incidents",
                filter: ["has", "point_count"],
                paint: {
                  "circle-color": ["step", ["get", "point_count"], "#51bbd6", 5, "#f1f075", 15, "#f28cb1"],
                  "circle-radius": ["step", ["get", "point_count"], 20, 5, 30, 15, 40],
                  "circle-opacity": 0.75,
                },
                layout: {
                  visibility: showClusters && !focusedDistrictId ? "visible" : "none",
                },
              },
              firstSymbolId,
            )
          }

          if (!map.getLayer("cluster-count")) {
            map.addLayer({
              id: "cluster-count",
              type: "symbol",
              source: "crime-incidents",
              filter: ["has", "point_count"],
              layout: {
                "text-field": "{point_count_abbreviated}",
                "text-font": ["DIN Offc Pro Medium", "Arial Unicode MS Bold"],
                "text-size": 12,
                visibility: showClusters && !focusedDistrictId ? "visible" : "none",
              },
              paint: {
                "text-color": "#ffffff",
              },
            })
          }

          if (sourceType === "cbu" && !map.getLayer("crime-points")) {
            map.addLayer({
              id: "crime-points",
              type: "circle",
              source: "crime-incidents",
              filter: ["!", ["has", "point_count"]],
              paint: {
                "circle-radius": [
                  "interpolate",
                  ["linear"],
                  ["zoom"],
                  8,
                  ["interpolate", ["linear"], ["get", "crime_count"], 0, 5, 100, 20],
                  12,
                  ["interpolate", ["linear"], ["get", "crime_count"], 0, 8, 100, 30],
                ],
                "circle-color": [
                  "match",
                  ["get", "level"],
                  "low",
                  "#47B39C",
                  "medium",
                  "#FFC154",
                  "high",
                  "#EC6B56",
                  "#888888",
                ],
                "circle-opacity": 0.7,
                "circle-stroke-width": 1,
                "circle-stroke-color": "#ffffff",
              },
              layout: {
                visibility: showClusters && !focusedDistrictId ? "visible" : "none",
              },
            })

            map.addLayer({
              id: "crime-count-labels",
              type: "symbol",
              source: "crime-incidents",
              filter: ["!", ["has", "point_count"]],
              layout: {
                "text-field": "{crime_count}",
                "text-font": ["DIN Offc Pro Medium", "Arial Unicode MS Bold"],
                "text-size": 12,
                visibility: showClusters && !focusedDistrictId ? "visible" : "none",
              },
              paint: {
                "text-color": "#ffffff",
              },
            })

            map.on("mouseenter", "crime-points", () => {
              map.getCanvas().style.cursor = "pointer"
            })

            map.on("mouseleave", "crime-points", () => {
              map.getCanvas().style.cursor = ""
            })

            const handleCrimePointClick = (e: any) => {
              if (!map) return

              // Stop event propagation
              e.originalEvent.stopPropagation()
              e.preventDefault()

              const features = map.queryRenderedFeatures(e.point, { layers: ["crime-points"] })

              if (features.length > 0) {
                const feature = features[0]
                const props = feature.properties
                const coordinates = (feature.geometry as any).coordinates.slice()

                // if (props) {
                //   if (props) {
                //     const popupHTML = `
                //       <div class="p-3">
                //         <h3 class="font-bold">${props.district_name}</h3>
                //         <div class="mt-2">
                //           <p>Total Crimes: <b>${props.crime_count}</b></p>
                //           <p>Crime Level: <b>${props.level}</b></p>
                //           <p>Year: ${props.year} - Month: ${props.month}</p>
                //           ${filterCategory !== "all" ? `<p>Category: ${filterCategory}</p>` : ""}
                //         </div>
                //       </div>
                //     `

                //     new mapboxgl.Popup().setLngLat(coordinates).setHTML(popupHTML).addTo(map)
                //   }
                // }
              }
            }

            map.off("click", "crime-points", handleCrimePointClick)
            map.on("click", "crime-points", handleCrimePointClick)
          }

          map.on("mouseenter", "clusters", () => {
            map.getCanvas().style.cursor = "pointer"
          })

          map.on("mouseleave", "clusters", () => {
            map.getCanvas().style.cursor = ""
          })

          map.off("click", "clusters", handleClusterClick)
          map.on("click", "clusters", handleClusterClick)
        } else {
          try {
            const currentSource = map.getSource("crime-incidents") as mapboxgl.GeoJSONSource
            const data = (currentSource as any)._data

            const existingClusterState = (currentSource as any).options?.cluster
            const sourceTypeChanged =
              data.features.length > 0 &&
              ((sourceType === "cbu" && !data.features[0].properties.isCBU) ||
                (sourceType !== "cbu" && data.features[0].properties.isCBU))

            if (existingClusterState !== clusteringEnabled || sourceTypeChanged) {
              if (map.getLayer("clusters")) map.removeLayer("clusters")
              if (map.getLayer("cluster-count")) map.removeLayer("cluster-count")
              if (map.getLayer("unclustered-point")) map.removeLayer("unclustered-point")
              if (map.getLayer("crime-points")) map.removeLayer("crime-points")
              if (map.getLayer("crime-count-labels")) map.removeLayer("crime-count-labels")

              map.removeSource("crime-incidents")

              let features: GeoJSON.Feature[] = []

              if (sourceType === "cbu") {
                features = crimes.map(crime => ({
                  type: "Feature",
                  properties: {
                    district_id: crime.district_id,
                    district_name: crime.districts ? crime.districts.name : "Unknown",
                    crime_count: crime.number_of_crime || 0,
                    level: crime.level,
                    category: filterCategory !== "all" ? filterCategory : "All",
                    year: crime.year,
                    month: crime.month,
                    isCBU: true,
                  },
                  geometry: {
                    type: "Point",
                    coordinates: [
                      crime.districts?.geographics?.[0]?.longitude || 0,
                      crime.districts?.geographics?.[0]?.latitude || 0,
                    ],
                  },
                })) as GeoJSON.Feature[]
              } else {
                features = extractCrimeIncidents(crimes, filterCategory).filter(Boolean) as GeoJSON.Feature[]
              }

              map.addSource("crime-incidents", {
                type: "geojson",
                data: {
                  type: "FeatureCollection",
                  features: features,
                },
                cluster: clusteringEnabled,
                clusterMaxZoom: 14,
                clusterRadius: 50,
              })

              if (!map.getLayer("clusters")) {
                map.addLayer(
                  {
                    id: "clusters",
                    type: "circle",
                    source: "crime-incidents",
                    filter: ["has", "point_count"],
                    paint: {
                      "circle-color": ["step", ["get", "point_count"], "#51bbd6", 5, "#f1f075", 15, "#f28cb1"],
                      "circle-radius": ["step", ["get", "point_count"], 20, 5, 30, 15, 40],
                      "circle-opacity": 0.75,
                    },
                    layout: {
                      visibility: showClusters && !focusedDistrictId ? "visible" : "none",
                    },
                  },
                  firstSymbolId,
                )
              }

              if (!map.getLayer("cluster-count")) {
                map.addLayer({
                  id: "cluster-count",
                  type: "symbol",
                  source: "crime-incidents",
                  filter: ["has", "point_count"],
                  layout: {
                    "text-field": "{point_count_abbreviated}",
                    "text-font": ["DIN Offc Pro Medium", "Arial Unicode MS Bold"],
                    "text-size": 12,
                    visibility: showClusters && !focusedDistrictId ? "visible" : "none",
                  },
                  paint: {
                    "text-color": "#ffffff",
                  },
                })
              }

              if (sourceType === "cbu") {
                if (!map.getLayer("crime-points")) {
                  map.addLayer({
                    id: "crime-points",
                    type: "circle",
                    source: "crime-incidents",
                    filter: ["!", ["has", "point_count"]],
                    paint: {
                      "circle-radius": [
                        "interpolate",
                        ["linear"],
                        ["zoom"],
                        8,
                        ["interpolate", ["linear"], ["get", "crime_count"], 0, 5, 100, 20],
                        12,
                        ["interpolate", ["linear"], ["get", "crime_count"], 0, 8, 100, 30],
                      ],
                      "circle-color": [
                        "match",
                        ["get", "level"],
                        "low",
                        "#47B39C",
                        "medium",
                        "#FFC154",
                        "high",
                        "#EC6B56",
                        "#888888",
                      ],
                      "circle-opacity": 0.7,
                      "circle-stroke-width": 1,
                      "circle-stroke-color": "#ffffff",
                    },
                    layout: {
                      visibility: showClusters && !focusedDistrictId ? "visible" : "none",
                    },
                  })

                  map.addLayer({
                    id: "crime-count-labels",
                    type: "symbol",
                    source: "crime-incidents",
                    filter: ["!", ["has", "point_count"]],
                    layout: {
                      "text-field": "{crime_count}",
                      "text-font": ["DIN Offc Pro Medium", "Arial Unicode MS Bold"],
                      "text-size": 12,
                      visibility: showClusters && !focusedDistrictId ? "visible" : "none",
                    },
                    paint: {
                      "text-color": "#ffffff",
                    },
                  })

                  map.on("mouseenter", "crime-points", () => {
                    map.getCanvas().style.cursor = "pointer"
                  })

                  map.on("mouseleave", "crime-points", () => {
                    map.getCanvas().style.cursor = ""
                  })

                  const handleCrimePointClick = (e: any) => {
                    if (!map) return

                    // Stop event propagation
                    e.originalEvent.stopPropagation()
                    e.preventDefault()

                    const features = map.queryRenderedFeatures(e.point, { layers: ["crime-points"] })

                    if (features.length > 0) {
                      const feature = features[0]
                      const props = feature.properties
                      const coordinates = (feature.geometry as any).coordinates.slice()

                      // if (props) {
                      //   const popupHTML = `
                      //     <div class="p-3">
                      //       <h3 class="font-bold">${props.district_name}</h3>
                      //       <div class="mt-2">
                      //         <p>Total Crimes: <b>${props.crime_count}</b></p>
                      //         <p>Crime Level: <b>${props.level}</b></p>
                      //         <p>Year: ${props.year} - Month: ${props.month}</p>
                      //         ${filterCategory !== "all" ? `<p>Category: ${filterCategory}</p>` : ""}
                      //       </div>
                      //     </div>
                      //   `

                      //   new mapboxgl.Popup().setLngLat(coordinates).setHTML(popupHTML).addTo(map)
                      // }
                    }
                  }

                  map.off("click", "crime-points", handleCrimePointClick)
                  map.on("click", "crime-points", handleCrimePointClick)
                }
              }
            }
          } catch (error) {
            console.error("Error updating cluster source:", error)
          }

          if (map.getLayer("clusters")) {
            map.setLayoutProperty("clusters", "visibility", showClusters && !focusedDistrictId ? "visible" : "none")
          }

          if (map.getLayer("cluster-count")) {
            map.setLayoutProperty(
              "cluster-count",
              "visibility",
              showClusters && !focusedDistrictId ? "visible" : "none",
            )
          }

          if (sourceType === "cbu" && map.getLayer("crime-points")) {
            map.setLayoutProperty(
              "crime-points",
              "visibility",
              showClusters && !focusedDistrictId ? "visible" : "none",
            )
            map.setLayoutProperty(
              "crime-count-labels",
              "visibility",
              showClusters && !focusedDistrictId ? "visible" : "none",
            )
          }

          map.off("click", "clusters", handleClusterClick)
          map.on("click", "clusters", handleClusterClick)
        }
      } catch (error) {
        console.error("Error adding cluster layer:", error)
      }
    }

    if (map.isStyleLoaded()) {
      onStyleLoad()
    } else {
      map.once("style.load", onStyleLoad)
    }

    return () => {
      if (map) {
        map.off("click", "clusters", handleClusterClick)
        if (sourceType === "cbu" && map.getLayer("crime-points")) {
          // Define properly typed event handlers
          const crimePointsMouseEnter = () => {
            if (map && map.getCanvas()) {
              map.getCanvas().style.cursor = "pointer";
            }
          };

          const crimePointsMouseLeave = () => {
            if (map && map.getCanvas()) {
              map.getCanvas().style.cursor = "";
            }
          };

          const crimePointsClick = (e: mapboxgl.MapMouseEvent) => {
            if (!map) return;

            e.originalEvent.stopPropagation();
            e.preventDefault();

            const features = map.queryRenderedFeatures(e.point, { layers: ["crime-points"] });

            if (features.length > 0) {
              const feature = features[0];
              const props = feature.properties;
              const coordinates = (feature.geometry as any).coordinates.slice();

              // if (props) {
              //   const popupHTML = `
              //     <div class="p-3">
              //       <h3 class="font-bold">${props.district_name}</h3>
              //       <div class="mt-2">
              //         <p>Total Crimes: <b>${props.crime_count}</b></p>
              //         <p>Crime Level: <b>${props.level}</b></p>
              //         <p>Year: ${props.year} - Month: ${props.month}</p>
              //         ${filterCategory !== "all" ? `<p>Category: ${filterCategory}</p>` : ""}
              //       </div>
              //     </div>
              //   `;

              //   // new mapboxgl.Popup()
              //   //   .setLngLat(coordinates)
              //   //   .setHTML(popupHTML)
              //   //   .addTo(map);
              // }
            }
          };

          // Remove event listeners with properly typed handlers
          map.off("mouseenter", "crime-points", crimePointsMouseEnter);
          map.off("mouseleave", "crime-points", crimePointsMouseLeave);
          map.off("click", "crime-points", crimePointsClick);
        }
      }
    }
  }, [
    map,
    visible,
    crimes,
    filterCategory,
    focusedDistrictId,
    handleClusterClick,
    clusteringEnabled,
    showClusters,
    sourceType,
  ])

  useEffect(() => {
    if (!map || !map.getSource("crime-incidents")) return

    try {
      let features: GeoJSON.Feature[]

      if (sourceType === "cbu") {
        features = crimes.map(crime => ({
          type: "Feature",
          properties: {
            district_id: crime.district_id,
            district_name: crime.districts ? crime.districts.name : "Unknown",
            crime_count: crime.number_of_crime || 0,
            level: crime.level,
            category: filterCategory !== "all" ? filterCategory : "All",
            year: crime.year,
            month: crime.month,
            isCBU: true,
          },
          geometry: {
            type: "Point",
            coordinates: [
              crime.districts?.geographics?.[0]?.longitude || 0,
              crime.districts?.geographics?.[0]?.latitude || 0,
            ],
          },
        })) as GeoJSON.Feature[]
      } else {
        features = extractCrimeIncidents(crimes, filterCategory).filter(Boolean) as GeoJSON.Feature[]
      }

      ; (map.getSource("crime-incidents") as mapboxgl.GeoJSONSource).setData({
        type: "FeatureCollection",
        features: features,
      })
    } catch (error) {
      console.error("Error updating incident data:", error)
    }
  }, [map, crimes, filterCategory, sourceType])

  useEffect(() => {
    if (!map) return

    try {
      if (map.getLayer("clusters")) {
        map.setLayoutProperty("clusters", "visibility", showClusters && !focusedDistrictId ? "visible" : "none")
      }

      if (map.getLayer("cluster-count")) {
        map.setLayoutProperty(
          "cluster-count",
          "visibility",
          showClusters && !focusedDistrictId ? "visible" : "none",
        )
      }

      if (sourceType === "cbu") {
        if (map.getLayer("crime-points")) {
          map.setLayoutProperty(
            "crime-points",
            "visibility",
            showClusters && !focusedDistrictId ? "visible" : "none",
          )
        }

        if (map.getLayer("crime-count-labels")) {
          map.setLayoutProperty(
            "crime-count-labels",
            "visibility",
            showClusters && !focusedDistrictId ? "visible" : "none",
          )
        }
      }
    } catch (error) {
      console.error("Error updating cluster visibility:", error)
    }
  }, [map, showClusters, focusedDistrictId, sourceType])

  return null
}
