// SPDX-FileCopyrightText: 2025 Contributors to the CitrineOS Project
//
// SPDX-License-Identifier: Apache-2.0
'use client';

import React, { useEffect, useRef, useState } from 'react';
import { GeoPoint } from '@lib/utils/GeoPoint';
import type { LocationPickerMapProps } from '@lib/client/components/map/types';
import L from 'leaflet';
import markerIcon2x from 'leaflet/dist/images/marker-icon-2x.png';
import markerIcon from 'leaflet/dist/images/marker-icon.png';
import markerShadow from 'leaflet/dist/images/marker-shadow.png';

// @ts-ignore
delete L.Icon.Default.prototype._getIconUrl;
L.Icon.Default.mergeOptions({
  iconRetinaUrl: markerIcon2x.src || markerIcon2x,
  iconUrl: markerIcon.src || markerIcon,
  shadowUrl: markerShadow.src || markerShadow,
});

export const defaultLatitude = 36.7783;
export const defaultLongitude = -119.4179;
const defaultZoom = 15;

/**
 * MapLocationPicker component that allows selecting a location on the map (OSM/Leaflet)
 */
export const MapLocationPicker: React.FC<LocationPickerMapProps> = ({
  point,
  zoom = defaultZoom,
  onLocationSelect,
}) => {
  const mapRef = useRef<HTMLDivElement>(null);
  const leafletMapRef = useRef<L.Map | null>(null);
  const markerRef = useRef<L.Marker | null>(null);

  const [position, setPosition] = useState<{ lat: number; lng: number } | undefined>(
    point
      ? {
          lat: point.latitude,
          lng: point.longitude,
        }
      : undefined,
  );

  useEffect(() => {
    if (point) {
      setPosition({
        lat: point.latitude,
        lng: point.longitude,
      });
    } else {
      setPosition(undefined);
    }
  }, [point]);

  // Initialize map
  useEffect(() => {
    if (!mapRef.current || leafletMapRef.current) return;

    const center = point
      ? [point.latitude, point.longitude]
      : [defaultLatitude, defaultLongitude];

    const map = L.map(mapRef.current, {
      center: center as [number, number],
      zoom: zoom,
      zoomControl: true,
    });

    L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
      attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
      maxZoom: 19,
    }).addTo(map);

    map.on('click', (e: L.LeafletMouseEvent) => {
      const lat = e.latlng.lat;
      const lng = e.latlng.lng;
      onLocationSelect(new GeoPoint(lat, lng));

      if (markerRef.current) {
        markerRef.current.setLatLng([lat, lng]);
      } else {
        markerRef.current = L.marker([lat, lng]).addTo(map);
      }
    });

    leafletMapRef.current = map;

    return () => {
      map.remove();
      leafletMapRef.current = null;
      markerRef.current = null;
    };
  }, []); // eslint-disable-line react-hooks/exhaustive-deps

  // Update marker position when point changes
  useEffect(() => {
    if (!leafletMapRef.current) return;

    if (position) {
      if (markerRef.current) {
        markerRef.current.setLatLng([position.lat, position.lng]);
      } else {
        markerRef.current = L.marker([position.lat, position.lng]).addTo(leafletMapRef.current);
      }
      leafletMapRef.current.panTo([position.lat, position.lng]);
    } else if (markerRef.current) {
      markerRef.current.remove();
      markerRef.current = null;
    }
  }, [position]);

  return (
    <div
      ref={mapRef}
      style={{ width: '100%', height: '100%', minHeight: '300px', borderRadius: '8px' }}
    />
  );
};
