"use client"

import type { IUnclusteredPointLayerProps } from "@/app/_utils/types/map"
import { useEffect, useCallback, useRef } from "react"
import { manageLayerVisibility } from "@/app/_utils/map/layer-visibility"

export default function UnclusteredPointLayer({
    visible = true,
    map,
    crimes = [],
    filterCategory = "all",
    focusedDistrictId,
}: IUnclusteredPointLayerProps) {
    // Add a ref to track if we're currently interacting with a marker
    const isInteractingWithMarker = useRef(false);

    // Define layer IDs for consistent management
    const LAYER_IDS = ['unclustered-point'];

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

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

            // Set flag to indicate we're interacting with a marker
            isInteractingWithMarker.current = true;

            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)

            // Ensure markers stay visible when clicking on them
            if (map.getLayer("unclustered-point")) {
                map.setLayoutProperty("unclustered-point", "visibility", "visible");
            }

            // First fly to the incident location
            map.flyTo({
                center: [incidentDetails.longitude, incidentDetails.latitude],
                zoom: 15,
                bearing: 0,
                pitch: 45,
                duration: 2000,
            })

            // Then dispatch the incident_click event to show the popup
            const customEvent = new CustomEvent("incident_click", {
                detail: incidentDetails,
                bubbles: true,
            })

            // Dispatch on both the map canvas and document to ensure it's caught
            map.getCanvas().dispatchEvent(customEvent)
            document.dispatchEvent(customEvent)

            // Reset the flag after a delay to allow the event to process
            setTimeout(() => {
                isInteractingWithMarker.current = false;
            }, 500);
        },
        [map],
    );

    // Use centralized layer visibility management
    useEffect(() => {
        if (!map) return;

        // Special case for this layer: also consider focusedDistrictId
        const isActuallyVisible = visible && !(focusedDistrictId && !isInteractingWithMarker.current);

        return manageLayerVisibility(map, LAYER_IDS, isActuallyVisible);
    }, [map, visible, focusedDistrictId]);

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

        // 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 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: {
                                // Only hide markers if a district is focused AND we're not interacting with a marker
                                visibility: focusedDistrictId && !isInteractingWithMarker.current ? "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, but keep visible when interacting with markers
                    const newVisibility = focusedDistrictId && !isInteractingWithMarker.current ? "none" : "visible";
                    map.setLayoutProperty("unclustered-point", "visibility", newVisibility);
                }

                // 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)
            }
        }

        if (map.getLayer("crime-incidents")) {
            const newVisibility = focusedDistrictId && !isInteractingWithMarker.current ? "none" : "visible";
            map.setLayoutProperty("crime-incidents", "visibility", newVisibility);
        }

        if (map.getLayer("unclustered-point")) {
            const newVisibility = focusedDistrictId && !isInteractingWithMarker.current ? "none" : "visible";
            map.setLayoutProperty("unclustered-point", "visibility", newVisibility);
        }

        // 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])

    return null
}
