"use client"

import { IUnclusteredPointLayerProps } from "@/app/_utils/types/map"
import { useEffect, useCallback } from "react"

export default function UnclusteredPointLayer({
    visible = true,
    map,
    crimes = [],
    filterCategory = "all",
    focusedDistrictId,
}: IUnclusteredPointLayerProps) {
    // Konversi crimes ke GeoJSON FeatureCollection
    const geojsonData = {
        type: "FeatureCollection" as const,
        features: crimes.flatMap((crime) =>
            crime.crime_incidents
                .filter(
                    (incident) =>
                        (filterCategory === "all" || incident.crime_categories.name === filterCategory) &&
                        incident.locations &&
                        typeof incident.locations.longitude === "number" &&
                        typeof incident.locations.latitude === "number"
                )
                .map((incident) => ({
                    type: "Feature" as const,
                    geometry: {
                        type: "Point" as const,
                        coordinates: [incident.locations.longitude, incident.locations.latitude],
                    },
                    properties: {
                        id: incident.id,
                        district: crime.districts.name,
                        category: incident.crime_categories.name,
                        incidentType: incident.crime_categories.type || "",
                        description: incident.description,
                        status: incident.status || "",
                        timestamp: incident.timestamp ? incident.timestamp.toString() : "",
                    },
                }))
        ),
    }

    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(incident.properties.timestamp || Date.now()),
            }

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

            // Create a custom event with incident details
            const customEvent = new CustomEvent("incident_click", {
                detail: incidentDetails,
                bubbles: true,
            })

            // Dispatch the event on both the map canvas and document to ensure it's captured
            if (map.getCanvas()) {
                map.getCanvas().dispatchEvent(customEvent)
            }
            document.dispatchEvent(customEvent)

            // Also trigger a fly-to event to zoom to the incident
            const flyToEvent = new CustomEvent("mapbox_fly_to", {
                detail: {
                    longitude: incidentDetails.longitude,
                    latitude: incidentDetails.latitude,
                    zoom: 15,
                    bearing: 0,
                    pitch: 45,
                    duration: 1000,
                },
                bubbles: true,
            })

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

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

        const setupLayerAndSource = () => {
            try {
                // First check if source exists and update it
                if (map.getSource("crime-incidents")) {
                    (map.getSource("crime-incidents") as any).setData(geojsonData);
                } else {
                    // If not, add source
                    map.addSource("crime-incidents", {
                        type: "geojson",
                        data: geojsonData,
                    });
                }

                // Get layers to find first symbol layer
                const layers = map.getStyle().layers;
                let firstSymbolId: string | undefined;
                for (const layer of layers) {
                    if (layer.type === "symbol") {
                        firstSymbolId = layer.id;
                        break;
                    }
                }

                // Check if layer exists
                if (!map.getLayer("unclustered-point")) {
                    map.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: focusedDistrictId ? "none" : "visible",
                            },
                        },
                        firstSymbolId,
                    );

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

                    map.on("mouseleave", "unclustered-point", () => {
                        map.getCanvas().style.cursor = "";
                    });
                } else {
                    // Update visibility based on focused district
                    map.setLayoutProperty("unclustered-point", "visibility", focusedDistrictId ? "none" : "visible");
                }

                // Always ensure click handler is properly registered
                map.off("click", "unclustered-point", handleIncidentClick);
                map.on("click", "unclustered-point", handleIncidentClick);
            } catch (error) {
                console.error("Error setting up unclustered point layer:", error);
            }
        };

        // Check if style is loaded and set up layer accordingly
        if (map.isStyleLoaded()) {
            setupLayerAndSource();
        } else {
            // Add event listener for style loading completion
            const onStyleLoad = () => {
                setupLayerAndSource();
            };

            map.once("style.load", onStyleLoad);

            // Also wait a bit and try again as a fallback
            setTimeout(() => {
                if (map.isStyleLoaded()) {
                    setupLayerAndSource();
                }
            }, 500);
        }

        return () => {
            if (map) {
                map.off("click", "unclustered-point", handleIncidentClick);
            }
        };
    }, [map, visible, focusedDistrictId, handleIncidentClick, crimes, filterCategory, geojsonData]);

    return null;
}
