import { useEffect, useRef } from 'react';
import L from 'leaflet';
import 'leaflet/dist/leaflet.css';

type Props = {
    latitude: string;
    longitude: string;
    radiusMeters: string;
    onChange: (latitude: string, longitude: string) => void;
    height?: number;
};

export default function AreaMapPicker({ latitude, longitude, radiusMeters, onChange, height = 320 }: Props) {
    const containerRef = useRef<HTMLDivElement>(null);
    const mapRef = useRef<L.Map | null>(null);
    const markerRef = useRef<L.Marker | null>(null);
    const circleRef = useRef<L.Circle | null>(null);
    const onChangeRef = useRef(onChange);

    useEffect(() => {
        onChangeRef.current = onChange;
    }, [onChange]);

    useEffect(() => {
        if (!containerRef.current || mapRef.current) return;

        const initialLat = Number(latitude) || 0.5402;
        const initialLng = Number(longitude) || 123.0595;
        const map = L.map(containerRef.current, { scrollWheelZoom: true }).setView([initialLat, initialLng], Number(latitude) && Number(longitude) ? 14 : 5);

        L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
            attribution: '&copy; OpenStreetMap contributors',
            maxZoom: 19,
        }).addTo(map);

        const updatePoint = (lat: number, lng: number) => {
            onChangeRef.current(lat.toFixed(7), lng.toFixed(7));
            if (!markerRef.current) {
                markerRef.current = L.marker([lat, lng], { draggable: true }).addTo(map);
                markerRef.current.on('dragend', () => {
                    const position = markerRef.current?.getLatLng();
                    if (position) onChangeRef.current(position.lat.toFixed(7), position.lng.toFixed(7));
                });
            } else {
                markerRef.current.setLatLng([lat, lng]);
            }
        };

        map.on('click', (event: L.LeafletMouseEvent) => updatePoint(event.latlng.lat, event.latlng.lng));
        mapRef.current = map;
        setTimeout(() => map.invalidateSize(), 100);

        return () => {
            map.remove();
            mapRef.current = null;
            markerRef.current = null;
            circleRef.current = null;
        };
    }, []);

    useEffect(() => {
        const map = mapRef.current;
        if (!map) return;
        const lat = Number(latitude);
        const lng = Number(longitude);
        const radius = Number(radiusMeters);
        if (!Number.isFinite(lat) || !Number.isFinite(lng)) return;

        if (!markerRef.current) {
            markerRef.current = L.marker([lat, lng], { draggable: true }).addTo(map);
            markerRef.current.on('dragend', () => {
                const position = markerRef.current?.getLatLng();
                if (position) onChangeRef.current(position.lat.toFixed(7), position.lng.toFixed(7));
            });
        } else {
            markerRef.current.setLatLng([lat, lng]);
        }

        if (Number.isFinite(radius) && radius > 0) {
            if (!circleRef.current) {
                circleRef.current = L.circle([lat, lng], { radius, weight: 2, fillOpacity: 0.08 }).addTo(map);
            } else {
                circleRef.current.setLatLng([lat, lng]);
                circleRef.current.setRadius(radius);
            }
        } else if (circleRef.current) {
            circleRef.current.removeFrom(map);
            circleRef.current = null;
        }
    }, [latitude, longitude, radiusMeters]);

    return (
        <div className="space-y-2">
            <div ref={containerRef} style={{ height }} className="w-full overflow-hidden rounded-lg border" />
            <p className="text-xs text-muted-foreground">
                Klik peta untuk memilih titik pusat Area atau geser marker. Lingkaran mengikuti nilai Radius (meter).
            </p>
        </div>
    );
}
