import { Input } from "@/components/ui/input";
import { fetchAddressSuggestions, type AddressSuggestion } from "@/lib/addressAutocomplete";
import { cn } from "@/lib/utils";
import { Loader2, MapPinned } from "lucide-react";
import { useEffect, useRef, useState } from "react";

type AddressAutocompleteInputProps = {
  id: string;
  value: string;
  onValueChange: (value: string) => void;
  onSuggestionSelected: (suggestion: AddressSuggestion) => void;
  placeholder?: string;
  disabled?: boolean;
  className?: string;
};

export function AddressAutocompleteInput({
  id,
  value,
  onValueChange,
  onSuggestionSelected,
  placeholder,
  disabled,
  className,
}: AddressAutocompleteInputProps) {
  const [suggestions, setSuggestions] = useState<AddressSuggestion[]>([]);
  const [isOpen, setIsOpen] = useState(false);
  const [isLoading, setIsLoading] = useState(false);
  const [errorMessage, setErrorMessage] = useState<string | null>(null);
  const [hasSearched, setHasSearched] = useState(false);

  const closeTimeoutRef = useRef<number | null>(null);
  const skipNextFetchRef = useRef(false);

  useEffect(() => {
    const trimmedValue = value.trim();

    if (skipNextFetchRef.current) {
      skipNextFetchRef.current = false;
      return;
    }

    if (trimmedValue.length < 3) {
      setSuggestions([]);
      setIsOpen(false);
      setIsLoading(false);
      setHasSearched(false);
      setErrorMessage(null);
      return;
    }

    const controller = new AbortController();
    const timeoutId = window.setTimeout(async () => {
      setIsLoading(true);
      setErrorMessage(null);
      setIsOpen(true);

      try {
        const nextSuggestions = await fetchAddressSuggestions(trimmedValue, controller.signal);
        setSuggestions(nextSuggestions);
        setHasSearched(true);
      } catch (error) {
        if (controller.signal.aborted) {
          return;
        }

        console.error(error);
        setSuggestions([]);
        setHasSearched(true);
        setIsOpen(true);
        setErrorMessage("Impossible de charger les suggestions pour le moment.");
      } finally {
        if (!controller.signal.aborted) {
          setIsLoading(false);
        }
      }
    }, 300);

    return () => {
      controller.abort();
      window.clearTimeout(timeoutId);
    };
  }, [value]);

  useEffect(() => {
    return () => {
      if (closeTimeoutRef.current) {
        window.clearTimeout(closeTimeoutRef.current);
      }
    };
  }, []);

  const showSuggestionsPanel = isOpen && value.trim().length >= 3;
  const showEmptyState = showSuggestionsPanel && hasSearched && !isLoading && !errorMessage && suggestions.length === 0;

  const handleBlur = () => {
    closeTimeoutRef.current = window.setTimeout(() => {
      setIsOpen(false);
    }, 120);
  };

  const handleFocus = () => {
    if (closeTimeoutRef.current) {
      window.clearTimeout(closeTimeoutRef.current);
      closeTimeoutRef.current = null;
    }

    if (value.trim().length >= 3 && (suggestions.length > 0 || errorMessage || hasSearched)) {
      setIsOpen(true);
    }
  };

  const handleSelectSuggestion = (suggestion: AddressSuggestion) => {
    skipNextFetchRef.current = true;
    onValueChange(suggestion.addressLine);
    onSuggestionSelected(suggestion);
    setSuggestions([]);
    setHasSearched(false);
    setErrorMessage(null);
    setIsOpen(false);
  };

  return (
    <div className={cn("relative", className)}>
      <Input
        id={id}
        value={value}
        onChange={(event) => onValueChange(event.target.value)}
        onFocus={handleFocus}
        onBlur={handleBlur}
        placeholder={placeholder}
        autoComplete="street-address"
        disabled={disabled}
      />
      <p className="text-muted-foreground mt-1 text-xs">
        Commencez a saisir une adresse pour recevoir des propositions automatiques.
      </p>

      {showSuggestionsPanel ? (
        <div className="bg-popover text-popover-foreground absolute left-0 right-0 top-full z-30 mt-2 overflow-hidden rounded-md border shadow-lg">
          {isLoading ? (
            <div className="text-muted-foreground flex items-center gap-2 px-3 py-3 text-sm">
              <Loader2 className="h-4 w-4 animate-spin" />
              Recherche d'adresses...
            </div>
          ) : null}

          {!isLoading && errorMessage ? (
            <div className="text-muted-foreground px-3 py-3 text-sm">{errorMessage}</div>
          ) : null}

          {showEmptyState ? (
            <div className="text-muted-foreground px-3 py-3 text-sm">
              Aucune adresse n'a ete trouvee pour cette saisie.
            </div>
          ) : null}

          {!isLoading && !errorMessage && suggestions.length > 0 ? (
            <div className="max-h-72 overflow-y-auto py-1">
              {suggestions.map((suggestion) => (
                <button
                  key={suggestion.label}
                  type="button"
                  className="hover:bg-accent hover:text-accent-foreground flex w-full items-start gap-3 px-3 py-3 text-left transition-colors"
                  onMouseDown={(event) => event.preventDefault()}
                  onClick={() => handleSelectSuggestion(suggestion)}
                >
                  <MapPinned className="text-primary mt-0.5 h-4 w-4 shrink-0" />
                  <div className="min-w-0">
                    <div className="text-sm font-medium">{suggestion.addressLine}</div>
                    <div className="text-muted-foreground text-xs">
                      {suggestion.postcode} {suggestion.city}
                    </div>
                  </div>
                </button>
              ))}
            </div>
          ) : null}
        </div>
      ) : null}
    </div>
  );
}
