"use client"

import { useEffect, useRef, useCallback } from "react"
import { useMap } from "react-map-gl/mapbox"
import type { ICrimes } from "@/app/_utils/types/crimes"

export interface CrimeClusterLayerProps {
    visible?: boolean
    crimes: ICrimes[]
    filterCategory: string | "all"
    isTimelapsePlaying?: boolean
    beforeId?: string
}

export default function CrimeClusterLayer({
    visible = true,
    crimes = [],
    filterCategory = "all",
    isTimelapsePlaying = false,
    beforeId,
}: CrimeClusterLayerProps) {
    const { current: map } = useMap()
    const layersAdded = useRef(false)

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

            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
                ; (map.getSource("crime-incidents") as mapboxgl.GeoJSONSource).getClusterExpansionZoom(clusterId, (err, zoom) => {
                    if (err) return

                    map.easeTo({
                        center: (features[0].geometry as any).coordinates,
                        zoom: zoom ?? undefined,
                    })
                })
        },
        [map],
    )

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

            const features = map.queryRenderedFeatures(e.point, { layers: ["unclustered-point"] })
            if (!features || features.length === 0) return

            const incident = features[0]
            if (!incident.properties) return

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

            const incidentDetails = {
                id: incident.properties.id,
                district: incident.properties.district,
                category: incident.properties.category,
                type: incident.properties.incidentType,
                description: incident.properties.description,
                status: incident.properties?.status || "Unknown",
                longitude: (incident.geometry as any).coordinates[0],
                latitude: (incident.geometry as any).coordinates[1],
                timestamp: new Date(),
            }

            console.log("Incident clicked:", incidentDetails)

            const customEvent = new CustomEvent("incident_click", {
                detail: incidentDetails,
                bubbles: true,
            })

            if (map.getMap().getCanvas()) {
                map.getMap().getCanvas().dispatchEvent(customEvent)
            } else {
                document.dispatchEvent(customEvent)
            }
        },
        [map],
    )

    // Initialize crime clusters and points
    useEffect(() => {
        if (!map || !visible || crimes.length === 0) return

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

            try {
                // Get the first symbol layer
                let firstSymbolId = beforeId
                if (!firstSymbolId) {
                    const layers = map.getStyle().layers
                    for (const layer of layers) {
                        if (layer.type === "symbol") {
                            firstSymbolId = layer.id
                            break
                        }
                    }
                }

                if (!map.getMap().getSource("crime-incidents")) {
                    const allIncidents = crimes.flatMap((crime) => {
                        let filteredIncidents = crime.crime_incidents

                        if (filterCategory !== "all") {
                            filteredIncidents = crime.crime_incidents.filter(
                                (incident) => incident.crime_categories.name === filterCategory,
                            )
                        }

                        return filteredIncidents.map((incident) => ({
                            type: "Feature" as const,
                            properties: {
                                id: incident.id,
                                district: crime.districts.name,
                                category: incident.crime_categories.name,
                                incidentType: incident.crime_categories.type,
                                level: crime.level,
                                description: incident.description,
                            },
                            geometry: {
                                type: "Point" as const,
                                coordinates: [incident.locations.longitude, incident.locations.latitude],
                            },
                        }))
                    })

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

                    if (!map.getMap().getLayer("clusters")) {
                        map.getMap().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: isTimelapsePlaying ? "none" : "visible",
                                },
                            },
                            firstSymbolId,
                        )
                    }

                    if (!map.getMap().getLayer("cluster-count")) {
                        map.getMap().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": isTimelapsePlaying ? "none" : "visible",
                            },
                            paint: {
                                "text-color": "#ffffff",
                            },
                        })
                    }

                    if (!map.getMap().getLayer("unclustered-point")) {
                        map.getMap().addLayer(
                            {
                                id: "unclustered-point",
                                type: "circle",
                                source: "crime-incidents",
                                filter: ["!", ["has", "point_count"]],
                                paint: {
                                    "circle-color": "#11b4da",
                                    "circle-radius": 8,
                                    "circle-stroke-width": 1,
                                    "circle-stroke-color": "#fff",
                                },
                                layout: {
                                    visibility: isTimelapsePlaying ? "none" : "visible",
                                },
                            },
                            firstSymbolId,
                        )
                    }

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

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

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

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

                    // Attach click handlers
                    map.off("click", "clusters", handleClusterClick)
                    map.off("click", "unclustered-point", handleIncidentClick)

                    map.on("click", "clusters", handleClusterClick)
                    map.on("click", "unclustered-point", handleIncidentClick)

                    layersAdded.current = true
                }
            } catch (error) {
                console.error("Error adding crime cluster layers:", error)
            }
        }

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

        return () => {
            if (map) {
                map.off("click", "clusters", handleClusterClick)
                map.off("click", "unclustered-point", handleIncidentClick)
            }
        }
    }, [map, visible, crimes, filterCategory, handleClusterClick, handleIncidentClick, beforeId, isTimelapsePlaying])

    // Update crime data when filters change
    useEffect(() => {
        if (!map || !map.getMap().getSource("crime-incidents")) return

        try {
            // If timeline is playing, hide all point/cluster layers to improve performance
            if (isTimelapsePlaying) {
                // Hide all incident points during timelapse
                if (map.getMap().getLayer("clusters")) {
                    map.getMap().setLayoutProperty("clusters", "visibility", "none")
                }
                if (map.getMap().getLayer("unclustered-point")) {
                    map.getMap().setLayoutProperty("unclustered-point", "visibility", "none")
                }
                if (map.getMap().getLayer("cluster-count")) {
                    map.getMap().setLayoutProperty("cluster-count", "visibility", "none")
                }

                // Update the source with empty data to free up resources
                ; (map.getMap().getSource("crime-incidents") as mapboxgl.GeoJSONSource).setData({
                    type: "FeatureCollection",
                    features: [],
                })
            } else {
                // When not playing, show all layers again
                if (map.getMap().getLayer("clusters")) {
                    map.getMap().setLayoutProperty("clusters", "visibility", "visible")
                }
                if (map.getMap().getLayer("unclustered-point")) {
                    map.getMap().setLayoutProperty("unclustered-point", "visibility", "visible")
                }
                if (map.getMap().getLayer("cluster-count")) {
                    map.getMap().setLayoutProperty("cluster-count", "visibility", "visible")
                }

                // Restore detailed incidents when timelapse stops
                const allIncidents = crimes.flatMap((crime) => {
                    if (!crime.crime_incidents) return []

                    let filteredIncidents = crime.crime_incidents

                    if (filterCategory !== "all") {
                        filteredIncidents = crime.crime_incidents.filter(
                            (incident) => incident.crime_categories && incident.crime_categories.name === filterCategory,
                        )
                    }

                    return filteredIncidents
                        .map((incident) => {
                            if (!incident.locations) {
                                console.warn("Missing location for incident:", incident.id)
                                return null
                            }

                            return {
                                type: "Feature" as const,
                                properties: {
                                    id: incident.id,
                                    district: crime.districts?.name || "Unknown",
                                    category: incident.crime_categories?.name || "Unknown",
                                    incidentType: incident.crime_categories?.type || "Unknown",
                                    level: crime.level || "low",
                                    description: incident.description || "",
                                },
                                geometry: {
                                    type: "Point" as const,
                                    coordinates: [incident.locations.longitude || 0, incident.locations.latitude || 0],
                                },
                            }
                        })
                        .filter(Boolean)
                })

                    // Update the source with detailed data
                    ; (map.getMap().getSource("crime-incidents") as mapboxgl.GeoJSONSource).setData({
                        type: "FeatureCollection",
                        features: allIncidents as GeoJSON.Feature[],
                    })
            }
        } catch (error) {
            console.error("Error updating incident data:", error)
        }
    }, [map, crimes, filterCategory, isTimelapsePlaying])

    return null
}
