import * as React from 'react';
import { useState, useEffect } from 'react';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Alert, AlertDescription } from '@/components/ui/alert';
import { Map, MapMarker } from './Map';
import { GeolocationService, Location } from '@/services/geolocationService';
import { MapPin, Loader2, Search, Navigation } from 'lucide-react';

interface LocationPickerProps {
  onLocationSelect: (location: Location) => void;
  initialLocation?: Location;
  label?: string;
  title?: string;
  description?: string;
  placeholder?: string;
  required?: boolean;
  className?: string;
}

export function LocationPicker({
  onLocationSelect,
  initialLocation,
  label = "Sélectionner une position",
  title,
  description,
  placeholder = "Entrez une adresse ou cliquez sur la carte",
  required = false,
  className = ""
}: LocationPickerProps) {
  const [selectedLocation, setSelectedLocation] = useState<Location | null>(initialLocation || null);
  const [addressInput, setAddressInput] = useState('');
  const [isSearching, setIsSearching] = useState(false);
  const [isGettingLocation, setIsGettingLocation] = useState(false);
  const [error, setError] = useState('');
  
  const geoService = new GeolocationService();
  const abidjanBounds = {
    north: 5.41,
    south: 5.26,
    east: -3.95,
    west: -4.10
  };

  useEffect(() => {
    if (initialLocation) {
      setSelectedLocation(initialLocation);
      if (initialLocation.address) {
        setAddressInput(initialLocation.address);
      }
    }
  }, [initialLocation]);

  const handleMapClick = async (lat: number, lng: number) => {
    const location: Location = { lat, lng };
    
    // Check if within service area
    if (!geoService.isWithinServiceArea(location)) {
      setError('Cette position est en dehors de notre zone de service (Abidjan)');
      return;
    }

    setError('');
    setSelectedLocation(location);
    
    // Try to get address
    try {
      const address = await geoService.reverseGeocode(location.lat, location.lng);
      const locationWithAddress = { ...location, address };
      setSelectedLocation(locationWithAddress);
      setAddressInput(address);
      onLocationSelect(locationWithAddress);
    } catch (error) {
      onLocationSelect(location);
    }
  };

  const handleAddressSearch = async () => {
    if (!addressInput.trim()) return;

    setIsSearching(true);
    setError('');

    try {
      const address = addressInput + ', Abidjan, Côte d\'Ivoire';
      // For now, use default Abidjan location since geocode is not implemented
      const location = { lat: 5.3364, lng: -4.0267, address: addressInput };
      
      if (!geoService.isWithinServiceArea(location)) {
        setError('Cette adresse est en dehors de notre zone de service (Abidjan)');
        return;
      }

      setSelectedLocation(location);
      onLocationSelect(location);
    } catch (error) {
      setError(error instanceof Error ? error.message : 'Erreur lors de la recherche d\'adresse');
    } finally {
      setIsSearching(false);
    }
  };

  const handleCurrentLocation = async () => {
    setIsGettingLocation(true);
    setError('');

    try {
      const location = await geoService.getCurrentPosition();
      
      if (!geoService.isWithinServiceArea(location)) {
        setError('Votre position actuelle est en dehors de notre zone de service (Abidjan)');
        return;
      }

      // Get address for current location
      try {
        const address = await geoService.reverseGeocode(location.lat, location.lng);
        const locationWithAddress = { ...location, address };
        setSelectedLocation(locationWithAddress);
        setAddressInput(address);
        onLocationSelect(locationWithAddress);
      } catch (error) {
        setSelectedLocation(location);
        onLocationSelect(location);
      }
    } catch (error) {
      setError(error instanceof Error ? error.message : 'Erreur lors de l\'obtention de votre position');
    } finally {
      setIsGettingLocation(false);
    }
  };

  const markers: MapMarker[] = selectedLocation && 
    typeof selectedLocation.lat === 'number' && 
    typeof selectedLocation.lng === 'number' ? [{
    id: 'selected',
    lat: selectedLocation.lat,
    lng: selectedLocation.lng,
    title: 'Position sélectionnée',
    type: 'destination',
    info: selectedLocation.address || 'Position personnalisée'
  }] : [];

  const mapCenter: [number, number] = selectedLocation && 
    typeof selectedLocation.lat === 'number' && 
    typeof selectedLocation.lng === 'number'
    ? [selectedLocation.lat, selectedLocation.lng]
    : [5.3364, -4.0267]; // Default Abidjan center

  return (
    <div className={`space-y-4 ${className}`}>
      {label && (
        <Label className="text-base font-medium">
          {label}
          {required && <span className="text-red-500 ml-1">*</span>}
        </Label>
      )}

      {/* Address Search */}
      <div className="flex gap-2">
        <div className="flex-1">
          <Input
            value={addressInput}
            onChange={(e) => setAddressInput(e.target.value)}
            placeholder={placeholder}
            onKeyPress={(e) => e.key === 'Enter' && handleAddressSearch()}
            data-testid="address-input"
          />
        </div>
        <Button
          type="button"
          variant="outline"
          onClick={handleAddressSearch}
          disabled={isSearching || !addressInput.trim()}
          data-testid="search-address"
        >
          {isSearching ? (
            <Loader2 className="h-4 w-4 animate-spin" />
          ) : (
            <Search className="h-4 w-4" />
          )}
        </Button>
        <Button
          type="button"
          variant="outline"
          onClick={handleCurrentLocation}
          disabled={isGettingLocation}
          data-testid="current-location"
        >
          {isGettingLocation ? (
            <Loader2 className="h-4 w-4 animate-spin" />
          ) : (
            <Navigation className="h-4 w-4" />
          )}
        </Button>
      </div>

      {/* Error Display */}
      {error && (
        <Alert variant="destructive">
          <AlertDescription>{error}</AlertDescription>
        </Alert>
      )}

      {/* Map */}
      <div className="relative">
        <Map
          center={mapCenter}
          zoom={selectedLocation ? 15 : 11}
          markers={markers}
          onMapClick={handleMapClick}
          height="300px"
          interactive={true}
          data-testid="location-map"
        />
        
        {/* Map Instructions */}
        <div className="absolute top-2 left-2 bg-white/90 backdrop-blur-sm rounded-lg p-3 shadow-lg max-w-xs">
          <div className="flex items-center gap-2 text-sm">
            <MapPin className="h-4 w-4 text-primary" />
            <span className="font-medium">Cliquez sur la carte pour sélectionner</span>
          </div>
          <p className="text-xs text-muted-foreground mt-1">
            Ou utilisez la recherche d'adresse ci-dessus
          </p>
        </div>
      </div>

      {/* Selected Location Info */}
      {selectedLocation && (
        <div className="bg-green-50 border border-green-200 rounded-lg p-3">
          <div className="flex items-center gap-2 text-green-800">
            <MapPin className="h-4 w-4" />
            <span className="font-medium">Position sélectionnée</span>
          </div>
          <p className="text-sm text-green-700 mt-1">
            {selectedLocation.address || `${selectedLocation.lat.toFixed(4)}, ${selectedLocation.lng.toFixed(4)}`}
          </p>
        </div>
      )}
    </div>
  );
}