import { useState, useCallback, useEffect } from 'react';
import { useDebounce } from '@/hooks/useDebounce';
import { supabase } from '@/integrations/supabase/client';
import { Input } from '@/components/ui/input';
import { Button } from '@/components/ui/button';
import { Card } from '@/components/ui/card';
import { MapPin, Loader2, X } from 'lucide-react';
import { ParkLocationMap } from '@/components/maps/ParkLocationMap';
import { logger } from '@/lib/logger';

interface LocationResult {
  place_id: number;
  display_name: string;
  lat: string;
  lon: string;
  address: {
    city?: string;
    town?: string;
    village?: string;
    state?: string;
    country?: string;
    postcode?: string;
  };
}

interface SelectedLocation {
  name: string;
  city?: string;
  state_province?: string;
  country: string;
  postal_code?: string;
  latitude: number;
  longitude: number;
  timezone?: string;
  display_name: string; // Full OSM display name for reference
}

interface LocationSearchProps {
  onLocationSelect: (location: SelectedLocation) => void;
  initialLocationId?: string;
  className?: string;
}

export function LocationSearch({ onLocationSelect, initialLocationId, className }: LocationSearchProps): React.JSX.Element {
  const [searchQuery, setSearchQuery] = useState('');
  const [results, setResults] = useState<LocationResult[]>([]);
  const [isSearching, setIsSearching] = useState(false);
  const [searchError, setSearchError] = useState<string | null>(null);
  const [selectedLocation, setSelectedLocation] = useState<SelectedLocation | null>(null);
  const [showResults, setShowResults] = useState(false);
  
  const debouncedSearch = useDebounce(searchQuery, 500);

  // Load initial location if editing
  useEffect(() => {
    if (initialLocationId) {
      void loadInitialLocation(initialLocationId);
    }
  }, [initialLocationId]);

  const loadInitialLocation = async (locationId: string): Promise<void> => {
    const { data, error } = await supabase
      .from('locations')
      .select('id, name, city, state_province, country, postal_code, latitude, longitude, timezone')
      .eq('id', locationId)
      .maybeSingle();

    if (data && !error) {
      setSelectedLocation({
        name: data.name,
        city: data.city || undefined,
        state_province: data.state_province || undefined,
        country: data.country,
        postal_code: data.postal_code || undefined,
        latitude: parseFloat(data.latitude?.toString() || '0'),
        longitude: parseFloat(data.longitude?.toString() || '0'),
        timezone: data.timezone || undefined,
        display_name: data.name, // Use name as display for existing locations
      });
    }
  };

  const searchLocations = useCallback(async (query: string) => {
    if (!query || query.length < 3) {
      setResults([]);
      setSearchError(null);
      return;
    }

    setIsSearching(true);
    setSearchError(null);
    try {
      const response = await fetch(
        `https://nominatim.openstreetmap.org/search?format=json&q=${encodeURIComponent(query)}&addressdetails=1&limit=5`,
        {
          headers: {
            'User-Agent': 'ThemeParkDatabase/1.0',
          },
        }
      );
      
      // Check if response is OK and content-type is JSON
      if (!response.ok) {
        const errorMsg = `Location search failed (${response.status}). Please try again.`;
        console.error('OpenStreetMap API error:', response.status);
        setSearchError(errorMsg);
        setResults([]);
        setShowResults(false);
        return;
      }

      const contentType = response.headers.get('content-type');
      if (!contentType || !contentType.includes('application/json')) {
        const errorMsg = 'Invalid response from location service. Please try again.';
        console.error('Invalid response format from OpenStreetMap');
        setSearchError(errorMsg);
        setResults([]);
        setShowResults(false);
        return;
      }

      const data = await response.json() as LocationResult[];
      setResults(data);
      setShowResults(true);
      setSearchError(null);
    } catch {
      logger.error('Location search failed', { query: searchQuery });
      setSearchError('Failed to search locations. Please check your connection.');
      setResults([]);
      setShowResults(false);
    } finally {
      setIsSearching(false);
    }
  }, []);

  useEffect(() => {
    if (debouncedSearch) {
      void searchLocations(debouncedSearch);
    } else {
      setResults([]);
      setShowResults(false);
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [debouncedSearch]);

  const handleSelectResult = (result: LocationResult): void => {
    const latitude = parseFloat(result.lat);
    const longitude = parseFloat(result.lon);
    
    // Safely access address properties with fallback
    const address = result.address || {};
    const city = address.city || address.town || address.village;
    const state = address.state || '';
    const country = address.country || 'Unknown';
    
    const locationName = city 
      ? `${city}, ${state} ${country}`.trim()
      : result.display_name;

    // Build location data object (no database operations)
    const locationData: SelectedLocation = {
      name: locationName,
      city: city || undefined,
      state_province: state || undefined,
      country: country,
      postal_code: address.postcode || undefined,
      latitude,
      longitude,
      timezone: undefined, // Will be set by server during approval if needed
      display_name: result.display_name,
    };

    setSelectedLocation(locationData);
    setSearchQuery('');
    setResults([]);
    setShowResults(false);
    onLocationSelect(locationData);
  };

  const handleClear = (): void => {
    setSelectedLocation(null);
    setSearchQuery('');
    setResults([]);
    setShowResults(false);
  };

  return (
    <div className={className}>
      {!selectedLocation ? (
        <div className="space-y-2">
          <div className="relative">
            <MapPin className="absolute left-3 top-3 h-4 w-4 text-muted-foreground" />
            <Input
              type="text"
              placeholder="Search for a location (city, address, landmark...)"
              value={searchQuery}
              onChange={(e) => setSearchQuery(e.target.value)}
              className="pl-10"
            />
            {isSearching && (
              <Loader2 className="absolute right-3 top-3 h-4 w-4 animate-spin text-muted-foreground" />
            )}
          </div>

          {searchError && (
            <div className="text-sm text-destructive mt-1">
              {searchError}
            </div>
          )}

          {showResults && results.length > 0 && (
            <Card className="absolute z-50 w-full max-h-64 overflow-y-auto">
              <div className="divide-y">
                {results.map((result) => (
                  <button
                    type="button"
                    key={result.place_id}
                    onClick={() => void handleSelectResult(result)}
                    className="w-full text-left p-3 hover:bg-accent transition-colors"
                  >
                    <div className="flex items-start gap-2">
                      <MapPin className="h-4 w-4 mt-0.5 text-muted-foreground flex-shrink-0" />
                      <div className="flex-1 min-w-0">
                        <p className="text-sm font-medium truncate">{result.display_name}</p>
                        <p className="text-xs text-muted-foreground">
                          {result.lat}, {result.lon}
                        </p>
                      </div>
                    </div>
                  </button>
                ))}
              </div>
            </Card>
          )}
          
          {showResults && results.length === 0 && !isSearching && !searchError && (
            <div className="text-sm text-muted-foreground mt-1">
              No locations found. Try a different search term.
            </div>
          )}
        </div>
      ) : (
        <div className="space-y-4">
          <Card className="p-4">
            <div className="flex items-start justify-between gap-4">
              <div className="flex items-start gap-3 flex-1">
                <MapPin className="h-5 w-5 text-primary mt-0.5" />
                <div className="flex-1 min-w-0">
                  <p className="font-medium">{selectedLocation.name}</p>
                  <div className="text-sm text-muted-foreground space-y-1 mt-1">
                    {selectedLocation.city && <p>City: {selectedLocation.city}</p>}
                    {selectedLocation.state_province && <p>State/Province: {selectedLocation.state_province}</p>}
                    <p>Country: {selectedLocation.country}</p>
                    {selectedLocation.postal_code && <p>Postal Code: {selectedLocation.postal_code}</p>}
                    <p className="text-xs">
                      Coordinates: {selectedLocation.latitude.toFixed(6)}, {selectedLocation.longitude.toFixed(6)}
                    </p>
                  </div>
                </div>
              </div>
              <Button
                type="button"
                variant="ghost"
                size="sm"
                onClick={handleClear}
              >
                <X className="h-4 w-4" />
              </Button>
            </div>
          </Card>

          <ParkLocationMap
            latitude={selectedLocation.latitude}
            longitude={selectedLocation.longitude}
            parkName={selectedLocation.name}
            className="h-48"
          />
        </div>
      )}
    </div>
  );
}
