"use client"

import { Card, CardContent, CardHeader, CardTitle } from "@/app/_components/ui/card"
import { Skeleton } from "@/app/_components/ui/skeleton"
import MapView from "./map"
import { Button } from "@/app/_components/ui/button"
import { AlertCircle } from "lucide-react"
import { getMonthName } from "@/app/_utils/common"
import { useRef, useState, useCallback, useMemo, useEffect } from "react"
import { useFullscreen } from "@/app/_hooks/use-fullscreen"
import { Overlay } from "./overlay"
import MapLegend from "./legends/map-legend"
import UnitsLegend from "./legends/units-legend"
import TimelineLegend from "./legends/timeline-legend"
import { useGetAvailableYears, useGetCrimeCategories, useGetCrimes } from "@/app/(pages)/(admin)/dashboard/crime-management/crime-overview/_queries/queries"
import MapSelectors from "./controls/map-selector"

import { cn } from "@/app/_lib/utils"
import CrimePopup from "./pop-up/crime-popup"
import { $Enums, crime_categories, crime_incidents, crimes, demographics, districts, geographics, locations } from "@prisma/client"
import { CrimeTimelapse } from "./controls/bottom/crime-timelapse"
import { ITooltips } from "./controls/top/tooltips"
import CrimeSidebar from "./controls/left/sidebar/map-sidebar"
import Tooltips from "./controls/top/tooltips"
import { BASE_BEARING, BASE_PITCH, BASE_ZOOM } from "@/app/_utils/const/map"
import Layers from "./layers/layers"
import DistrictLayer, { DistrictFeature } from "./layers/district-layer-old"
import { useGetUnitsQuery } from "@/app/(pages)/(admin)/dashboard/crime-management/units/_queries/queries"

interface ICrimeIncident {
    id: string
    district?: string
    category?: string
    type_category?: string | null
    description?: string
    status: string
    address?: string | null
    timestamp?: Date
    latitude?: number
    longitude?: number
}

export default function CrimeMap() {
    const [sidebarCollapsed, setSidebarCollapsed] = useState(true)
    const [selectedDistrict, setSelectedDistrict] = useState<DistrictFeature | null>(null)
    const [selectedIncident, setSelectedIncident] = useState<ICrimeIncident | null>(null)
    const [showLegend, setShowLegend] = useState<boolean>(true)
    const [selectedCategory, setSelectedCategory] = useState<string | "all">("all")
    const [selectedYear, setSelectedYear] = useState<number>(2024)
    const [selectedMonth, setSelectedMonth] = useState<number | "all">("all")
    const [activeControl, setActiveControl] = useState<ITooltips>("incidents")
    const [yearProgress, setYearProgress] = useState(0)
    const [isTimelapsePlaying, setisTimelapsePlaying] = useState(false)
    const [isSearchActive, setIsSearchActive] = useState(false)
    const [showUnitsLayer, setShowUnitsLayer] = useState(false)
    const [useAllYears, setUseAllYears] = useState<boolean>(false)
    const [useAllMonths, setUseAllMonths] = useState<boolean>(false)

    const mapContainerRef = useRef<HTMLDivElement>(null)

    const { isFullscreen } = useFullscreen(mapContainerRef)

    const {
        data: availableYears,
        isLoading: isYearsLoading,
        error: yearsError
    } = useGetAvailableYears()

    const { data: categoriesData, isLoading: isCategoryLoading } = useGetCrimeCategories()

    const categories = useMemo(() =>
        categoriesData ? categoriesData.map(category => category.name) : []
        , [categoriesData])

    const {
        data: crimes,
        isLoading: isCrimesLoading,
        error: crimesError
    } = useGetCrimes()

    const { data: fetchedUnits, isLoading } = useGetUnitsQuery()

    useEffect(() => {
        if (activeControl === "heatmap" || activeControl === "timeline") {
            setUseAllYears(true);
            setUseAllMonths(true);
        } else {
            setUseAllYears(false);
            setUseAllMonths(false);
        }
    }, [activeControl]);

    const filteredByYearAndMonth = useMemo(() => {
        if (!crimes) return [];

        if (useAllYears) {
            if (useAllMonths) {
                return crimes;
            } else {
                return crimes.filter((crime) => {
                    return selectedMonth === "all" ? true : crime.month === selectedMonth;
                });
            }
        }

        return crimes.filter((crime) => {
            const yearMatch = crime.year === selectedYear;

            if (selectedMonth === "all" || useAllMonths) {
                return yearMatch;
            } else {
                return yearMatch && crime.month === selectedMonth;
            }
        });
    }, [crimes, selectedYear, selectedMonth, useAllYears, useAllMonths]);

    const filteredCrimes = useMemo(() => {
        if (!filteredByYearAndMonth) return []
        if (selectedCategory === "all") return filteredByYearAndMonth

        return filteredByYearAndMonth.map((crime) => {
            const filteredIncidents = crime.crime_incidents.filter(
                incident => incident.crime_categories.name === selectedCategory
            )

            return {
                ...crime,
                crime_incidents: filteredIncidents,
                number_of_crime: filteredIncidents.length
            }
        })
    }, [filteredByYearAndMonth, selectedCategory])

    useEffect(() => {
        const handleIncidentClickEvent = (e: CustomEvent) => {
            console.log("Received incident_click event:", e.detail);
            if (!e.detail || !e.detail.id) {
                console.error("Invalid incident data in event:", e.detail);
                return;
            }

            let foundIncident: ICrimeIncident | undefined;

            filteredCrimes.forEach(crime => {
                crime.crime_incidents.forEach(incident => {
                    if (incident.id === e.detail.id) {
                        foundIncident = {
                            id: incident.id,
                            district: crime.districts.name,
                            description: incident.description,
                            status: incident.status || "unknown",
                            timestamp: incident.timestamp,
                            category: incident.crime_categories.name,
                            type_category: incident.crime_categories.type,
                            address: incident.locations.address,
                            latitude: incident.locations.latitude,
                            longitude: incident.locations.longitude,
                        };
                    }
                });
            });

            if (!foundIncident) {
                console.error("Could not find incident with ID:", e.detail.id);
                return;
            }

            if (!foundIncident.latitude || !foundIncident.longitude) {
                console.error("Invalid incident coordinates:", foundIncident);
                return;
            }

            setSelectedDistrict(null);

            setSelectedIncident(foundIncident);
        };

        const mapContainer = mapContainerRef.current;

        document.removeEventListener('incident_click', handleIncidentClickEvent as EventListener);
        if (mapContainer) {
            mapContainer.removeEventListener('incident_click', handleIncidentClickEvent as EventListener);
        }

        document.addEventListener('incident_click', handleIncidentClickEvent as EventListener);

        if (mapContainer) {
            mapContainer.addEventListener('incident_click', handleIncidentClickEvent as EventListener);
        }

        return () => {
            document.removeEventListener('incident_click', handleIncidentClickEvent as EventListener);
            if (mapContainer) {
                mapContainer.removeEventListener('incident_click', handleIncidentClickEvent as EventListener);
            }
        };
    }, [filteredCrimes]);

    useEffect(() => {
        const handleMapFlyTo = (e: CustomEvent) => {
            if (!e.detail) {
                console.error("Invalid fly-to data:", e.detail);
                return;
            }

            const { longitude, latitude, zoom, bearing, pitch, duration } = e.detail;

            const mapInstance = mapContainerRef.current?.querySelector('.mapboxgl-map');
            if (!mapInstance) {
                console.error("Map instance not found");
                return;
            }

            const mapboxEvent = new CustomEvent('mapbox_fly', {
                detail: {
                    center: [longitude, latitude],
                    zoom: zoom || 15,
                    bearing: bearing || 0,
                    pitch: pitch || 45,
                    duration: duration || 2000
                },
                bubbles: true
            });

            mapInstance.dispatchEvent(mapboxEvent);
        };

        document.addEventListener('mapbox_fly_to', handleMapFlyTo as EventListener);

        return () => {
            document.removeEventListener('mapbox_fly_to', handleMapFlyTo as EventListener);
        };
    }, []);

    useEffect(() => {
        const handleMapReset = (e: CustomEvent) => {
            const { duration } = e.detail || { duration: 1500 };

            const mapInstance = mapContainerRef.current?.querySelector('.mapboxgl-map');
            if (!mapInstance) {
                console.error("Map instance not found");
                return;
            }

            const mapboxEvent = new CustomEvent('mapbox_fly', {
                detail: {
                    duration: duration,
                    resetCamera: true
                },
                bubbles: true
            });

            mapInstance.dispatchEvent(mapboxEvent);
        };

        document.addEventListener('mapbox_reset', handleMapReset as EventListener);

        return () => {
            document.removeEventListener('mapbox_reset', handleMapReset as EventListener);
        };
    }, []);

    const handlePopupClose = () => {
        setSelectedIncident(null);

        const mapInstance = mapContainerRef.current?.querySelector('.mapboxgl-map');

        if (mapInstance) {
            const resetEvent = new CustomEvent('mapbox_reset', {
                detail: {
                    duration: 1500,
                },
                bubbles: true
            });

            mapInstance.dispatchEvent(resetEvent);
        }
    }

    const handleTimelineChange = useCallback((year: number, month: number, progress: number) => {
        setSelectedYear(year)
        setSelectedMonth(month)
        setYearProgress(progress)
    }, [])

    const handleTimelinePlayingChange = useCallback((playing: boolean) => {
        setisTimelapsePlaying(playing)

        if (playing) {
            setSelectedIncident(null)
            setSelectedDistrict(null)
        }
    }, [])

    const resetFilters = useCallback(() => {
        setSelectedYear(2024)
        setSelectedMonth("all")
        setSelectedCategory("all")
    }, [])

    const getMapTitle = () => {
        if (useAllYears) {
            return `All Years Data ${selectedCategory !== "all" ? `- ${selectedCategory}` : ''}`;
        }

        let title = `${selectedYear}`;
        if (selectedMonth !== "all" && !useAllMonths) {
            title += ` - ${getMonthName(Number(selectedMonth))}`;
        }
        if (selectedCategory !== "all") {
            title += ` - ${selectedCategory}`;
        }
        return title;
    }

    const handleControlChange = (controlId: ITooltips) => {
        setActiveControl(controlId);

        if (controlId === "search") {
            setIsSearchActive(prev => !prev);
        }

        if (controlId === "units") {
            setShowUnitsLayer(true);
        } else if (showUnitsLayer) {
            setShowUnitsLayer(false);
        }

        if (controlId === "heatmap" || controlId === "timeline") {
            setUseAllYears(true);
            setUseAllMonths(true);
        } else {
            setUseAllYears(false);
            setUseAllMonths(false);
        }
    }

    const showTimelineLayer = activeControl === "timeline";

    return (
        <Card className="w-full p-0 border-none shadow-none h-96">
            <CardHeader className="flex flex-row pb-2 pt-0 px-0 items-center justify-between">
                <CardTitle>Crime Map {getMapTitle()}</CardTitle>
                <MapSelectors
                    availableYears={availableYears || []}
                    selectedYear={selectedYear}
                    setSelectedYear={setSelectedYear}
                    selectedMonth={selectedMonth}
                    setSelectedMonth={setSelectedMonth}
                    selectedCategory={selectedCategory}
                    setSelectedCategory={setSelectedCategory}
                    categories={categories}
                    isYearsLoading={isYearsLoading}
                    isCategoryLoading={isCategoryLoading}
                />
            </CardHeader>
            <CardContent className="p-0">
                {isCrimesLoading ? (
                    <div className="flex items-center justify-center h-96">
                        <Skeleton className="h-full w-full rounded-md" />
                    </div>
                ) : crimesError ? (
                    <div className="flex flex-col items-center justify-center h-96 gap-4">
                        <AlertCircle className="h-10 w-10 text-destructive" />
                        <p className="text-center">Failed to load crime data. Please try again later.</p>
                            <Button onClick={() => window.location.reload()}>Retry</Button>
                    </div>
                ) : (
                            <div className="relative h-[600px]" ref={mapContainerRef}>
                                <div className={cn(
                                    "transition-all duration-300 ease-in-out",
                                    !sidebarCollapsed && isFullscreen && "ml-[400px]"
                                )}>
                                    <MapView mapStyle="mapbox://styles/mapbox/dark-v11" className="h-[600px] w-full rounded-md">
                                        <Layers
                                            crimes={filteredCrimes || []}
                                            units={fetchedUnits || []}
                                            year={selectedYear.toString()}
                                            month={selectedMonth.toString()}
                                            filterCategory={selectedCategory}
                                            activeControl={activeControl}
                                            useAllData={useAllYears}
                                        />

                                        {selectedIncident && selectedIncident.latitude && selectedIncident.longitude && (
                                            <>
                                                <CrimePopup
                                                    longitude={selectedIncident.longitude}
                                                    latitude={selectedIncident.latitude}
                                                    onClose={handlePopupClose}
                                                    incident={selectedIncident}
                                                />
                                            </>
                                        )}

                                        {isFullscreen && (
                                            <>
                                                <div className="absolute flex w-full p-2">
                                                    <Tooltips
                                                        activeControl={activeControl}
                                                        onControlChange={handleControlChange}
                                                        selectedYear={selectedYear}
                                                        setSelectedYear={setSelectedYear}
                                                        selectedMonth={selectedMonth}
                                                        setSelectedMonth={setSelectedMonth}
                                                        selectedCategory={selectedCategory}
                                                        setSelectedCategory={setSelectedCategory}
                                                        availableYears={availableYears || []}
                                                        categories={categories}
                                                        crimes={filteredCrimes}
                                                    />
                                                </div>

                                                <CrimeSidebar
                                                    crimes={filteredCrimes || []}
                                                    defaultCollapsed={sidebarCollapsed}
                                                    selectedCategory={selectedCategory}
                                                    selectedYear={selectedYear}
                                                    selectedMonth={selectedMonth}
                                                />
                                                <div className="absolute bottom-20 right-0 z-10 p-2">
                                                    <MapLegend position="bottom-right" />
                                                </div>

                                                {isFullscreen && showUnitsLayer && (
                                                    <div className="absolute bottom-40 right-0 z-10 p-2">
                                                        <UnitsLegend
                                                            categories={categories}
                                                            position="bottom-right"
                                                        />
                                                    </div>
                                                )}

                                                {isFullscreen && showTimelineLayer && (
                                                    <div className="absolute bottom-40 right-0 z-10 p-2">
                                                        <TimelineLegend position="bottom-right" />
                                                    </div>
                                                )}
                                            </>
                                        )}

                                        {isFullscreen && (
                                            <div className="absolute flex w-full bottom-0">
                                                <CrimeTimelapse
                                                    startYear={2020}
                                                    endYear={2024}
                                                    autoPlay={false}
                                                    onChange={handleTimelineChange}
                                                    onPlayingChange={handleTimelinePlayingChange}
                                                />
                                            </div>
                                        )}
                                    </MapView>
                                </div>
                    </div>
                )}
            </CardContent>
        </Card>
    )
}
