import { useEffect, useRef, useState } from "react";
import {
  FlatList,
  Image,
  Text,
  TextInput,
  TouchableOpacity,
  View,
} from "react-native";

import { icons } from "@/constants";
import type { GoogleInputProps } from "@/types/type";

const googleApiKey = process.env.EXPO_PUBLIC_GOOGLE_API_KEY!;

interface Suggestion {
  placeId: string;
  text: string;
}

// Places API (New) — the legacy Places web service is unavailable to
// newer Google Cloud projects. Results are restricted to Lebanon.
const fetchSuggestions = async (input: string): Promise<Suggestion[]> => {
  const res = await fetch(
    "https://places.googleapis.com/v1/places:autocomplete",
    {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "X-Goog-Api-Key": googleApiKey,
      },
      body: JSON.stringify({
        input,
        languageCode: "en",
        includedRegionCodes: ["lb"],
      }),
    },
  );
  const data = await res.json();

  return (data.suggestions ?? [])
    .map((s: any) => ({
      placeId: s.placePrediction?.placeId as string,
      text: s.placePrediction?.text?.text as string,
    }))
    .filter((s: Suggestion) => s.placeId && s.text);
};

const fetchPlaceDetails = async (placeId: string) => {
  const res = await fetch(`https://places.googleapis.com/v1/places/${placeId}`, {
    headers: {
      "X-Goog-Api-Key": googleApiKey,
      "X-Goog-FieldMask": "location,formattedAddress",
    },
  });
  const data = await res.json();

  return {
    latitude: data.location?.latitude as number,
    longitude: data.location?.longitude as number,
    address: data.formattedAddress as string,
  };
};

export const GoogleTextInput = ({
  icon,
  initialLocation,
  containerStyles,
  textInputBackgroundColor,
  handlePress,
}: GoogleInputProps) => {
  const [query, setQuery] = useState("");
  const [suggestions, setSuggestions] = useState<Suggestion[]>([]);
  const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);

  useEffect(() => {
    if (debounceRef.current) clearTimeout(debounceRef.current);

    if (query.trim().length < 3) {
      setSuggestions([]);
      return;
    }

    debounceRef.current = setTimeout(async () => {
      try {
        setSuggestions(await fetchSuggestions(query));
      } catch (err) {
        console.log("[PLACES_AUTOCOMPLETE]: ", err);
      }
    }, 200);

    return () => {
      if (debounceRef.current) clearTimeout(debounceRef.current);
    };
  }, [query]);

  const onSelect = async (suggestion: Suggestion) => {
    setQuery(suggestion.text);
    setSuggestions([]);

    try {
      const details = await fetchPlaceDetails(suggestion.placeId);
      handlePress({
        latitude: details.latitude,
        longitude: details.longitude,
        address: suggestion.text,
      });
    } catch (err) {
      console.log("[PLACE_DETAILS]: ", err);
    }
  };

  return (
    <View
      className={`flex flex-row items-center justify-center relative z-50 rounded-xl ${containerStyles}`}
    >
      <View className="flex-1 mx-5">
        <View
          className="flex flex-row items-center rounded-full px-4 mt-1"
          style={{
            backgroundColor: textInputBackgroundColor || "white",
            shadowColor: "#d4d4d4",
          }}
        >
          <View className="justify-center items-center w-6 h-6">
            <Image
              source={icon ? icon : icons.search}
              alt="Search"
              className="w-6 h-6"
              resizeMode="contain"
            />
          </View>

          <TextInput
            value={query}
            onChangeText={setQuery}
            placeholder={initialLocation ?? "Where do you want to go?"}
            placeholderTextColor="gray"
            className="flex-1 p-3 text-base font-JakartaSemiBold"
          />
        </View>

        {suggestions.length > 0 && (
          <View
            className="rounded-xl mt-1"
            style={{
              backgroundColor: textInputBackgroundColor || "white",
              shadowColor: "#d4d4d4",
            }}
          >
            <FlatList
              data={suggestions}
              keyExtractor={(item) => item.placeId}
              keyboardShouldPersistTaps="handled"
              renderItem={({ item }) => (
                <TouchableOpacity
                  onPress={() => onSelect(item)}
                  className="p-3 border-b border-general-700"
                >
                  <Text className="text-base font-JakartaRegular">
                    {item.text}
                  </Text>
                </TouchableOpacity>
              )}
            />
          </View>
        )}
      </View>
    </View>
  );
};
