"use client";

import { useTranslations } from "next-intl";
import React, { useRef, useEffect, useState, useCallback } from "react";
import { toast } from "react-toastify";

/* ---------- INTERFACES ---------- */
interface DropdownOption {
  label: string;
  value: string;
  placeId?: string;
}

interface AddressSearchDropdownProps {
  label?: string;
  placeholder?: string;
  selected: DropdownOption | null;
  onSearchChange?: (value: string) => void;
  onSelect?: (option: DropdownOption | null) => void;
  options: DropdownOption[];
  error?: string | { message?: string };
  loading?: boolean;
}

interface GoogleAddress {
  street_number: string;
  street: string;
  house_number: string;
  city: string;
  state: string;
  postal_code: string;
  country: string;
  latitude: string;
  longitude: string;
}

interface SecureAddressAutocompleteProps {
  value?: Partial<GoogleAddress>;
  onChange: (data: GoogleAddress) => void;
  placeholder?: string;
  error?: string | { message?: string };
  label?: string;
}

/* ---------- ADDRESS SEARCH DROPDOWN COMPONENT ---------- */
const AddressSearchDropdown: React.FC<AddressSearchDropdownProps> = ({
  label,
  placeholder,
  selected,
  onSearchChange,
  onSelect,
  options,
  error,
  loading = false,
}) => {
  const [search, setSearch] = useState<string>("");
  const [showList, setShowList] = useState<boolean>(false);
  const [highlightedIndex, setHighlightedIndex] = useState<number>(-1);

  const dropdownRef = useRef<HTMLDivElement | null>(null);
  const listRef = useRef<HTMLUListElement | null>(null);
  const inputRef = useRef<HTMLInputElement | null>(null);

  const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const value = e.target.value;
    setSearch(value);
    setShowList(true);
    onSearchChange?.(value);
  };

  const handleSelect = (option: DropdownOption) => {
    setSearch("");
    setShowList(false);
    setHighlightedIndex(-1);
    onSelect?.(option);
  };

  const handleClear = () => {
    setSearch("");
    setHighlightedIndex(-1);
    onSelect?.(null);
  };

  // Click outside to close dropdown
  useEffect(() => {
    const handleClickOutside = (e: MouseEvent) => {
      if (dropdownRef.current && !dropdownRef.current.contains(e.target as Node)) {
        setShowList(false);
      }
    };

    document.addEventListener("mousedown", handleClickOutside);
    return () => document.removeEventListener("mousedown", handleClickOutside);
  }, []);

  // Scroll highlighted item into view
  useEffect(() => {
    if (listRef.current && highlightedIndex >= 0) {
      listRef.current.children[highlightedIndex]?.scrollIntoView({ block: "nearest" });
    }
  }, [highlightedIndex]);

  // Keyboard navigation
  const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
    if (!showList && options.length > 0) {
      setShowList(true);
      return;
    }

    if (e.key === "ArrowDown") {
      e.preventDefault();
      setHighlightedIndex((prev) => (prev < options.length - 1 ? prev + 1 : 0));
    }

    if (e.key === "ArrowUp") {
      e.preventDefault();
      setHighlightedIndex((prev) => (prev > 0 ? prev - 1 : options.length - 1));
    }

    if (e.key === "Enter" && highlightedIndex >= 0) {
      e.preventDefault();
      handleSelect(options[highlightedIndex]);
    }

    if (e.key === "Escape") setShowList(false);
  };

  return (
    <div ref={dropdownRef} className="relative w-full">
      {label && (
        <label className="block text-sm font-semibold mb-2 text-gray-700">
          {label}
        </label>
      )}

      <div className="relative">
        <input
          ref={inputRef}
          value={search || selected?.label || ""}
          onChange={handleInputChange}
          onKeyDown={handleKeyDown}
          onFocus={() => options.length && setShowList(true)}
          placeholder={placeholder}
          className="w-full min-h-10 px-4 pr-10 py-2 text-sm border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
        />

        {loading && (
          <div className="absolute right-10 top-1/2 -translate-y-1/2">
            <div className="animate-spin h-4 w-4 border-2 border-blue-500 border-t-transparent rounded-full"></div>
          </div>
        )}

        {(search || selected) && !loading && (
          <button
            type="button"
            onClick={handleClear}
            className="absolute right-3 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600 text-lg font-bold"
          >
            ✕
          </button>
        )}
      </div>

      {showList && options.length > 0 && (
        <div className="absolute z-50 w-full mt-1 bg-white border border-gray-200 rounded-lg shadow-lg">
          <ul ref={listRef} className="max-h-60 overflow-y-auto text-sm">
            {options.map((opt, index) => (
              <li
                key={opt.value}
                onClick={() => handleSelect(opt)}
                className={`px-4 py-3 cursor-pointer transition-colors ${highlightedIndex === index
                  ? "bg-blue-50 text-blue-700 font-semibold"
                  : "hover:bg-gray-50"
                  }`}
              >
                {opt.label}
              </li>
            ))}
          </ul>
        </div>
      )}

      {error && (
        <p className="text-red-500 text-xs mt-1">
          {typeof error === "string" ? error : error.message}
        </p>
      )}
    </div>
  );
};

/* ---------- SECURE ADDRESS AUTOCOMPLETE COMPONENT ---------- */
const SecureAddressAutocomplete: React.FC<SecureAddressAutocompleteProps> = ({
  value,
  onChange,
  placeholder = "Enter address",
  error,
  label,
}) => {
  const searchTimerRef = useRef<NodeJS.Timeout | null>(null);
  const [predictions, setPredictions] = useState<DropdownOption[]>([]);
  const [selectedAddress, setSelectedAddress] = useState<DropdownOption | null>(null);
  const [loading, setLoading] = useState<boolean>(false);
  const t = useTranslations();
  /* ---------- SEARCH AUTOCOMPLETE ---------- */
  const handleSearchChange = useCallback(async (query: string) => {
    if (!query) {
      setPredictions([]);
      return;
    }

    if (searchTimerRef.current) clearTimeout(searchTimerRef.current);

    searchTimerRef.current = setTimeout(async () => {
      setLoading(true);
      try {
        const response = await fetch(`/api/autocomplete?input=${encodeURIComponent(query)}`);
        const data = await response.json();

        if (data.predictions) {
          setPredictions(
            data.predictions.map((r: any) => ({
              label: r.description,
              value: r.place_id,
              placeId: r.place_id,
            }))
          );
        } else {
          setPredictions([]);
        }
      } catch (error) {
        setPredictions([]);
      } finally {
        setLoading(false);
      }
    }, 300);
  }, []);

  /* ---------- SELECT ADDRESS & GET DETAILS ---------- */
  const handleAddressSelect = useCallback(
    async (selected: DropdownOption | null) => {
      if (!selected) {
        setSelectedAddress(null);
        return;
      }

      setLoading(true);
      try {
        const response = await fetch(`/api/place-details?placeId=${selected.placeId}`);
        const data = await response.json();

        if (!data.result) {
          toast.error(t("no_place_found"));
          return;
        }

        const place = data.result;
        const address: GoogleAddress = {
          street_number: "",
          street: "",
          house_number: "",
          city: "",
          state: "",
          postal_code: "",
          country: "",
          latitude: place.geometry?.location?.lat?.toString() || "",
          longitude: place.geometry?.location?.lng?.toString() || "",
        };

        place.address_components?.forEach((c: any) => {
          if (c.types.includes("street_number")) {
            address.street_number = c.long_name;
            address.house_number = c.long_name;
          }
          if (c.types.includes("route")) address.street = c.long_name;
          if (c.types.includes("locality")) address.city = c.long_name;
          if (c.types.includes("administrative_area_level_1")) address.state = c.long_name;
          if (c.types.includes("postal_code")) address.postal_code = c.long_name;
          if (c.types.includes("country")) address.country = c.long_name;
        });

        setSelectedAddress(selected);
        onChange(address);
      } catch (error) {
        // console.error("Place details error:", error);
      } finally {
        setLoading(false);
      }
    },
    [onChange]
  );

  return (
    <AddressSearchDropdown
      label={label}
      options={predictions}
      selected={selectedAddress}
      onSearchChange={handleSearchChange}
      onSelect={handleAddressSelect}
      placeholder={placeholder}
      error={error}
      loading={loading}
    />
  );
};

export default SecureAddressAutocomplete;