"use client"

import { useEffect, useState, useRef } from 'react';
import { useMap } from 'react-map-gl/mapbox';
import { CRIME_RATE_COLORS, MAPBOX_TILESET_ID } from '@/app/_utils/const/map';
import { DistrictPopup } from '../pop-up';

// Types for district properties
export interface DistrictFeature {
    id: string;
    name: string;
    properties: Record<string, any>;
    longitude?: number;
    latitude?: number;
    number_of_crime?: number;
    level?: 'low' | 'medium' | 'high' | 'critical';
}

// District layer props
export interface DistrictLayerProps {
    visible?: boolean;
    onClick?: (feature: DistrictFeature) => void;
    year?: string;
    month?: string;
    crimes?: Array<{
        id: string;
        district_name: string;
        distrcit_id?: string;
        number_of_crime?: number;
        level?: 'low' | 'medium' | 'high' | 'critical';
        incidents: any[];
    }>;
    tilesetId?: string;
}

export default function DistrictLayer({
    visible = true,
    onClick,
    year,
    month,
    crimes = [],
    tilesetId = MAPBOX_TILESET_ID
}: DistrictLayerProps) {
    const { current: map } = useMap();

    const [hoverInfo, setHoverInfo] = useState<{
        x: number;
        y: number;
        feature: any;
    } | null>(null);
    const [selectedDistrict, setSelectedDistrict] = useState<DistrictFeature | null>(null);

    // Use a ref to track whether layers have been added
    const layersAdded = useRef(false);

    // Process crime data to map to districts by district_id (kode_kec)
    const crimeDataByDistrict = crimes.reduce((acc, crime) => {
        // We'll use kode_kec as the key to match with tileset properties
        const districtId = crime.distrcit_id || crime.district_name;

        acc[districtId] = {
            number_of_crime: crime.number_of_crime,
            level: crime.level,
        };
        return acc;
    }, {} as Record<string, { number_of_crime?: number; level?: 'low' | 'medium' | 'high' | 'critical' }>);

    // Handle click on district
    const handleClick = (e: any) => {
        if (!map || !e.features || e.features.length === 0) return;

        const feature = e.features[0];
        const districtId = feature.properties.kode_kec; // Using kode_kec as the unique identifier
        const crimeData = crimeDataByDistrict[districtId] || {};

        const district: DistrictFeature = {
            id: districtId,
            name: feature.properties.nama || feature.properties.kecamatan,
            properties: feature.properties,
            longitude: e.lngLat.lng,
            latitude: e.lngLat.lat,
            ...crimeData,
        };

        if (onClick) {
            onClick(district);
        } else {
            setSelectedDistrict(district);
        }
    };

    // Handle mouse move for hover effect
    const handleMouseMove = (e: any) => {
        if (!map || !e.features || e.features.length === 0) return;

        const feature = e.features[0];
        const districtId = feature.properties.kode_kec; // Using kode_kec as the unique identifier
        const crimeData = crimeDataByDistrict[districtId] || {};

        // Enhance feature with crime data
        feature.properties = {
            ...feature.properties,
            ...crimeData,
        };

        setHoverInfo({
            x: e.point.x,
            y: e.point.y,
            feature: feature,
        });
    };

    // Add district layer to the map when it's loaded
    useEffect(() => {
        if (!map || !visible || layersAdded.current) return;

        // Handler for style load event
        const onStyleLoad = () => {
            // Skip if layers are already added or map is not available
            if (layersAdded.current || !map) return;

            try {
                // Add the vector tile source
                map.getMap().addSource('districts', {
                    type: 'vector',
                    url: `mapbox://${tilesetId}`
                });

                // Add the fill layer for districts
                map.getMap().addLayer({
                    id: 'district-fill',
                    type: 'fill',
                    source: 'districts',
                    'source-layer': 'Districts',
                    paint: {
                        'fill-color': [
                            'match',
                            ['get', 'level'],
                            'low', CRIME_RATE_COLORS.low,
                            'medium', CRIME_RATE_COLORS.medium,
                            'high', CRIME_RATE_COLORS.high,
                            'critical', CRIME_RATE_COLORS.critical,
                            CRIME_RATE_COLORS.default
                        ],
                        'fill-opacity': 0.6,
                    }
                });

                // Add the line layer for district borders
                map.getMap().addLayer({
                    id: 'district-line',
                    type: 'line',
                    source: 'districts',
                    'source-layer': 'Districts',
                    paint: {
                        'line-color': '#ffffff',
                        'line-width': 1,
                        'line-opacity': 0.5,
                    }
                });

                // Set event handlers
                map.on('click', 'district-fill', handleClick);
                map.on('mousemove', 'district-fill', handleMouseMove);
                map.on('mouseleave', 'district-fill', () => setHoverInfo(null));

                // Mark layers as added
                layersAdded.current = true;
                console.log('District layers added successfully');
            } catch (error) {
                console.error('Error adding district layers:', error);
            }
        };

        // If the map's style is already loaded, add the layers immediately
        if (map.isStyleLoaded()) {
            onStyleLoad();
        } else {
            // Otherwise, wait for the style.load event
            map.once('style.load', onStyleLoad);
        }

        // Cleanup function
        return () => {
            if (map && layersAdded.current) {
                map.off('click', 'district-fill', handleClick);
                map.off('mousemove', 'district-fill', handleMouseMove);
                map.off('mouseleave', 'district-fill', () => setHoverInfo(null));

                // If we want to remove the layers and source on component unmount:
                if (map.getLayer('district-line')) map.getMap().removeLayer('district-line');
                if (map.getLayer('district-fill')) map.getMap().removeLayer('district-fill');
                if (map.getSource('districts')) map.getMap().removeSource('districts');

                layersAdded.current = false;
            }
        };
    }, [map, visible, tilesetId]);

    // Update the crime data when it changes
    useEffect(() => {
        if (!map || !layersAdded.current) return;

        // Update the district-fill layer with new crime data
        try {
            // We need to update the layer paint property to correctly apply colors
            map.getMap().setPaintProperty('district-fill', 'fill-color', [
                'match',
                ['coalesce', ['get', 'level'], 'default'],
                'low', CRIME_RATE_COLORS.low,
                'medium', CRIME_RATE_COLORS.medium,
                'high', CRIME_RATE_COLORS.high,
                'critical', CRIME_RATE_COLORS.critical,
                CRIME_RATE_COLORS.default
            ]);
        } catch (error) {
            console.error('Error updating district layer:', error);
        }
    }, [map, crimes]);

    if (!visible) return null;

    return (
        <>
            {/* Hover tooltip */}
            {hoverInfo && (
                <div
                    className="absolute z-10 bg-white rounded-md shadow-md px-3 py-2 pointer-events-none"
                    style={{
                        left: hoverInfo.x + 10,
                        top: hoverInfo.y + 10,
                    }}
                >
                    <p className="text-sm font-medium">
                        {hoverInfo.feature.properties.nama || hoverInfo.feature.properties.kecamatan}
                    </p>
                    {hoverInfo.feature.properties.number_of_crime !== undefined && (
                        <p className="text-xs text-gray-600">
                            {hoverInfo.feature.properties.number_of_crime} incidents
                            {hoverInfo.feature.properties.level && (
                                <span className="ml-2 text-xs font-semibold text-gray-500">
                                    ({hoverInfo.feature.properties.level})
                                </span>
                            )}
                        </p>
                    )}
                </div>
            )}

            {/* District popup */}
            {selectedDistrict && selectedDistrict.longitude && selectedDistrict.latitude && (
                <DistrictPopup
                    longitude={selectedDistrict.longitude}
                    latitude={selectedDistrict.latitude}
                    onClose={() => setSelectedDistrict(null)}
                    district={selectedDistrict}
                    year={year}
                    month={month}
                />
            )}
        </>
    );
}
