"use client"

import { useEffect, useMemo, useState, useCallback } from "react"
import { Layer, Source } from "react-map-gl/mapbox"
import type { ICrimes } from "@/app/_utils/types/crimes"
import type mapboxgl from "mapbox-gl"
import { format } from "date-fns"
import { calculateAverageTimeOfDay } from "@/app/_utils/time"
import TimelinePopup from "../pop-up/timeline-popup"
import TimeZonesDisplay from "./timezone"

interface TimelineLayerProps {
    crimes: ICrimes[]
    year: string
    month: string
    filterCategory: string | "all"
    visible?: boolean
    map?: mapboxgl.Map | null
    useAllData?: boolean
}

export default function TimelineLayer({
    crimes,
    year,
    month,
    filterCategory,
    visible = false,
    map,
    useAllData = false,
}: TimelineLayerProps) {
    // State for selected district and popup
    const [selectedDistrict, setSelectedDistrict] = useState<any | null>(null)
    const [showTimeZones, setShowTimeZones] = useState<boolean>(true)

    // Process district data to extract average incident times
    const districtTimeData = useMemo(() => {
        // Group incidents by district
        const districtGroups = new Map<
            string,
            {
                districtId: string
                districtName: string
                incidents: Array<{ timestamp: Date; category: string }>
                center: [number, number]
            }
        >()

        crimes.forEach((crime) => {
            if (!crime.districts || !crime.district_id) return

            // Initialize district group if not exists
            if (!districtGroups.has(crime.district_id)) {
                // Find a central location for the district from any incident
                const centerIncident = crime.crime_incidents.find((inc) => inc.locations?.latitude && inc.locations?.longitude)

                const center: [number, number] = centerIncident
                    ? [centerIncident.locations.longitude, centerIncident.locations.latitude]
                    : [0, 0]

                districtGroups.set(crime.district_id, {
                    districtId: crime.district_id,
                    districtName: crime.districts.name,
                    incidents: [],
                  center,
              })
            }

            // Filter incidents appropriately before adding
            crime.crime_incidents.forEach((incident) => {
                // Skip invalid incidents
                if (!incident.timestamp) return
                if (filterCategory !== "all" && incident.crime_categories.name !== filterCategory) return

                // Add to appropriate district group
                const group = districtGroups.get(crime.district_id)
                if (group) {
                    group.incidents.push({
                        timestamp: new Date(incident.timestamp),
                      category: incident.crime_categories.name,
                  })
                }
            })
        })

        // Calculate average time for each district
        const result = Array.from(districtGroups.values())
            .filter((group) => group.incidents.length > 0 && group.center[0] !== 0)
            .map((group) => {
                const avgTimeInfo = calculateAverageTimeOfDay(group.incidents.map((inc) => inc.timestamp))

                return {
                    id: group.districtId,
                    name: group.districtName,
                    center: group.center,
                    avgHour: avgTimeInfo.hour,
                    avgMinute: avgTimeInfo.minute,
                    formattedTime: avgTimeInfo.formattedTime,
                    timeDescription: avgTimeInfo.description,
                    totalIncidents: group.incidents.length,
                  timeOfDay: avgTimeInfo.timeOfDay,
                  earliestTime: format(avgTimeInfo.earliest, "p"),
                  latestTime: format(avgTimeInfo.latest, "p"),
                  mostFrequentHour: avgTimeInfo.mostFrequentHour,
                  categoryCounts: group.incidents.reduce(
                      (acc, inc) => {
                        acc[inc.category] = (acc[inc.category] || 0) + 1
                        return acc
                    },
                    {} as Record<string, number>,
                ),
                }
            })

        return result
    }, [crimes, filterCategory, year, month])

    // Convert processed data to GeoJSON for display
    const timelineGeoJSON = useMemo(() => {
        return {
            type: "FeatureCollection" as const,
            features: districtTimeData.map((district) => ({
                type: "Feature" as const,
                properties: {
                    id: district.id,
                    name: district.name,
                    avgTime: district.formattedTime,
                    timeDescription: district.timeDescription,
                    totalIncidents: district.totalIncidents,
                    timeOfDay: district.timeOfDay,
                    hour: district.avgHour,
                    minute: district.avgMinute,
                },
                geometry: {
                    type: "Point" as const,
                    coordinates: district.center,
                },
            })),
        }
    }, [districtTimeData])

    // Handle marker click
    const handleMarkerClick = useCallback(
        (e: mapboxgl.MapMouseEvent & { features?: mapboxgl.MapboxGeoJSONFeature[] }) => {
            if (!e.features || e.features.length === 0) return

            const feature = e.features[0]
            const props = feature.properties
            if (!props) return

            // Get the corresponding district data for detailed info
            const districtData = districtTimeData.find((d) => d.id === props.id)
            if (!districtData) return

            // Fly to the location
            if (map) {
                map.flyTo({
                    center: districtData.center,
                    zoom: 12,
                    duration: 1000,
                    pitch: 45,
                    bearing: 0,
                })
            }

            // Set the selected district for popup
            setSelectedDistrict(districtData)
        },
        [map, districtTimeData],
    )

    // Handle popup close
    const handleClosePopup = useCallback(() => {
        setSelectedDistrict(null)
    }, [])

    // Add an effect to hide other layers when timeline is active
    useEffect(() => {
        if (!map || !visible) return

        // Hide incident markers when timeline mode is activated
        if (map.getLayer("unclustered-point")) {
            map.setLayoutProperty("unclustered-point", "visibility", "none")
        }

        // Hide clusters when timeline mode is activated
        if (map.getLayer("clusters")) {
            map.setLayoutProperty("clusters", "visibility", "none")
        }

        if (map.getLayer("cluster-count")) {
            map.setLayoutProperty("cluster-count", "visibility", "none")
        }

        // Set up event handlers
        const handleMouseEnter = () => {
            if (map) map.getCanvas().style.cursor = "pointer"
        }

        const handleMouseLeave = () => {
            if (map) map.getCanvas().style.cursor = ""
        }

        // Add event listeners
        if (map.getLayer("timeline-markers")) {
            map.on("click", "timeline-markers", handleMarkerClick)
            map.on("mouseenter", "timeline-markers", handleMouseEnter)
            map.on("mouseleave", "timeline-markers", handleMouseLeave)
        }

        return () => {
            // Clean up event listeners
            if (map) {
                map.off("click", "timeline-markers", handleMarkerClick)
                map.off("mouseenter", "timeline-markers", handleMouseEnter)
                map.off("mouseleave", "timeline-markers", handleMouseLeave)
            }
        }
    }, [map, visible, handleMarkerClick])

    // Clean up on unmount or when visibility changes
    useEffect(() => {
        if (!visible) {
            setSelectedDistrict(null)
        }
    }, [visible])

    if (!visible) return null

    return (
        <>
            <Source id="timeline-data" type="geojson" data={timelineGeoJSON}>
                {/* Digital clock background */}
                <Layer
                    id="timeline-markers-bg"
                    type="circle"
                    paint={{
                        "circle-color": [
                            "match",
                            ["get", "timeOfDay"],
                            "morning",
                            "#FFEB3B",
                            "afternoon",
                            "#FF9800",
                            "evening",
                            "#3F51B5",
                            "night",
                            "#263238",
                            "#4CAF50", // Default color
                        ],
                        "circle-radius": 18,
                        "circle-stroke-width": 2,
                        "circle-stroke-color": "#000000",
                        "circle-opacity": 0.9,
                    }}
                />

                {/* Digital clock display */}
                <Layer
                    id="timeline-markers"
                    type="symbol"
                    layout={{
                        "text-field": "{avgTime}",
                        "text-font": ["DIN Offc Pro Medium", "Arial Unicode MS Bold"],
                        "text-size": 12,
                        "text-anchor": "center",
                        "text-allow-overlap": true,
                    }}
                    paint={{
                        "text-color": [
                            "match",
                            ["get", "timeOfDay"],
                            "night",
                            "#FFFFFF",
                            "evening",
                            "#FFFFFF",
                            "#000000", // Default text color
                        ],
                        "text-halo-color": "#000000",
                        "text-halo-width": 0.5,
                    }}
                />
            </Source>

            {/* Custom Popup Component */}
            {selectedDistrict && (
                <TimelinePopup
                    longitude={selectedDistrict.center[0]}
                    latitude={selectedDistrict.center[1]}
                    onClose={handleClosePopup}
                    district={selectedDistrict}
                />
            )}


        </>
    )
}
