import { useState, useEffect, useCallback } from 'react';
import { geolocationService, type Location, type GeolocationOptions } from '@/services/geolocationService';

export interface UseGeolocationResult {
  location: Location | null;
  isLoading: boolean;
  error: string | null;
  accuracy: number | null;
  isSupported: boolean;
  getCurrentLocation: () => Promise<void>;
  startTracking: () => void;
  stopTracking: () => void;
  isTracking: boolean;
}

export function useGeolocation(options: GeolocationOptions = {}): UseGeolocationResult {
  const [location, setLocation] = useState<Location | null>(null);
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [accuracy, setAccuracy] = useState<number | null>(null);
  const [isTracking, setIsTracking] = useState(false);

  const isSupported = 'geolocation' in navigator;

  const getCurrentLocation = useCallback(async () => {
    if (!isSupported) {
      setError('Géolocalisation non supportée');
      return;
    }

    setIsLoading(true);
    setError(null);

    try {
      const currentLocation = await geolocationService.getCurrentPosition(options);
      setLocation(currentLocation);
      setAccuracy(currentLocation.accuracy || null);
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Erreur de géolocalisation');
    } finally {
      setIsLoading(false);
    }
  }, [isSupported, options]);

  const startTracking = useCallback(() => {
    if (!isSupported || isTracking) return;

    setIsTracking(true);
    setError(null);

    geolocationService.watchPosition(
      (newLocation) => {
        setLocation(newLocation);
        setAccuracy(newLocation.accuracy || null);
        setIsLoading(false);
      },
      (err) => {
        setError(err.message);
        setIsLoading(false);
      },
      options
    );
  }, [isSupported, isTracking, options]);

  const stopTracking = useCallback(() => {
    if (isTracking) {
      geolocationService.stopWatching();
      setIsTracking(false);
    }
  }, [isTracking]);

  // Cleanup on unmount
  useEffect(() => {
    return () => {
      stopTracking();
    };
  }, [stopTracking]);

  return {
    location,
    isLoading,
    error,
    accuracy,
    isSupported,
    getCurrentLocation,
    startTracking,
    stopTracking,
    isTracking
  };
}

// Hook for location picker functionality
export function useLocationPicker() {
  const [selectedLocation, setSelectedLocation] = useState<Location | null>(null);
  const [isPickingLocation, setIsPickingLocation] = useState(false);
  const { location: currentLocation, getCurrentLocation } = useGeolocation();

  const startPicking = useCallback(() => {
    setIsPickingLocation(true);
  }, []);

  const selectLocation = useCallback(async (lat: number, lng: number) => {
    setSelectedLocation({
      lat,
      lng,
      address: await geolocationService.reverseGeocode(lat, lng)
    });
    setIsPickingLocation(false);
  }, []);

  const useCurrentLocation = useCallback(async () => {
    await getCurrentLocation();
    if (currentLocation) {
      setSelectedLocation(currentLocation);
    }
  }, [getCurrentLocation, currentLocation]);

  const clearSelection = useCallback(() => {
    setSelectedLocation(null);
    setIsPickingLocation(false);
  }, []);

  return {
    selectedLocation,
    isPickingLocation,
    startPicking,
    selectLocation,
    useCurrentLocation,
    clearSelection,
    currentLocation
  };
}

// Hook for real-time tracking of couriers/delivery
export function useRealTimeTracking(targetId?: string) {
  const [trackedLocations, setTrackedLocations] = useState<Map<string, Location>>(new Map());
  const [isTracking, setIsTracking] = useState(false);
  const { startTracking, stopTracking, location } = useGeolocation({
    enableHighAccuracy: true,
    timeout: 5000,
    maximumAge: 30000
  });

  const startTrackingTarget = useCallback((id: string) => {
    setIsTracking(true);
    startTracking();
  }, [startTracking]);

  const stopTrackingTarget = useCallback(() => {
    setIsTracking(false);
    stopTracking();
  }, [stopTracking]);

  const updateTrackedLocation = useCallback((id: string, location: Location) => {
    setTrackedLocations(prev => new Map(prev.set(id, location)));
  }, []);

  // Update own location when tracking
  useEffect(() => {
    if (isTracking && location && targetId) {
      updateTrackedLocation(targetId, location);
    }
  }, [isTracking, location, targetId, updateTrackedLocation]);

  return {
    trackedLocations,
    isTracking,
    startTrackingTarget,
    stopTrackingTarget,
    updateTrackedLocation,
    currentLocation: location
  };
}