import React, { useState, useRef, useEffect } from "react";
import TextField from "@mui/material/TextField";
import { Box, List, ListItem } from "@mui/material";
import { useAppDispatch, useAppSelector } from "../../../../app/redux/hooks";
import {
  setAddressType,
  setLocationAsync,
  setUserLocation,
  setLocationVerifiedStatus,
} from "../../../../app/slices/common/locationSlice/locationSlice";
import LocationOnIcon from "@mui/icons-material/LocationOn";
import { showSnackbar } from "../../../../app/slices/common/customSnackBar/customSnackbarSlice";
import { getDecryptedToken } from "../../../../app/auth/authHandler";
import { LocationConfirmationPrompt } from "./LocationConfirmationPromt";
import CustomDialog from "../../../components/custom/dialog";

interface GoogleLocationSearchProps {
  onSelectLocation: (place: google.maps.places.PlaceResult) => void;
  onCloseModal: () => void;
}

const GoogleLocationSearch: React.FC<GoogleLocationSearchProps> = ({
  onSelectLocation,
  onCloseModal,
}) => {
  const dispatch = useAppDispatch();
  const [modalType, setModalType] = React.useState("");
  const [inputValue, setInputValue] = useState("");
  const [pId, setPlaceId] = useState("");
  const [description, setDescription] = useState("");
  const [predictions, setPredictions] = useState<
    google.maps.places.AutocompletePrediction[]
  >([]);
  const inputRef = useRef<HTMLInputElement>(null);
  const autocompleteServiceRef =
    useRef<google.maps.places.AutocompleteService | null>(null);
  const { addTocart } = useAppSelector((state) => state.CartState);
  const cartData = addTocart?.data;

  // Generate a session token for billing optimization
  const sessionTokenRef = useRef<
    google.maps.places.AutocompleteSessionToken | undefined
  >(undefined);

  useEffect(() => {
    // Wait for Google Maps API to be fully loaded
    const initializeAutoComplete = () => {
      if (window.google && window.google.maps && window.google.maps.places) {
        if (!autocompleteServiceRef.current) {
          autocompleteServiceRef.current =
            new window.google.maps.places.AutocompleteService();
          // Create a new session token
          sessionTokenRef.current =
            new window.google.maps.places.AutocompleteSessionToken();
        }
      } else {
        // Retry if Google Maps API is not yet loaded
        setTimeout(initializeAutoComplete, 500);
      }
    };

    initializeAutoComplete();
  }, []);
  const onOpenModal = (type: string) => {
    setModalType(type);
  };

  const handleInputChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
    const inputVal = e.target.value;
    setInputValue(inputVal);

    // Check if API is loaded and input has value
    if (!inputVal || !autocompleteServiceRef.current) {
      setPredictions([]);
      return;
    }

    // Ensure autocomplete service is initialized
    if (!autocompleteServiceRef.current) {
      console.warn(
        "Google Maps Autocomplete Service not yet initialized. Please try again."
      );
      return;
    }

    try {
      // Fetch place predictions with session token
      autocompleteServiceRef.current.getPlacePredictions(
        {
          input: inputVal,
          sessionToken: sessionTokenRef.current || undefined,
        },
        (predictions, status) => {
          if (
            status === google.maps.places.PlacesServiceStatus.OK &&
            predictions
          ) {
            setPredictions(predictions);
          } else if (
            status === google.maps.places.PlacesServiceStatus.ZERO_RESULTS
          ) {
            setPredictions([]);
          } else if (
            status !== google.maps.places.PlacesServiceStatus.INVALID_REQUEST
          ) {
            console.warn(
              "Google Places API error:",
              status,
              "Check your API key and permissions"
            );
            setPredictions([]);
          }
        }
      );
    } catch (error) {
      console.error("Error fetching predictions:", error);
      setPredictions([]);
    }
  };
  const onModalCloseCallback = (event: any) => {
    if (event === "confirmed") {
      handlePredictionAfterConfirmation(pId);
    }
  };

  const handlePredictionClick = (placeId: string, description: string) => {
    setPlaceId(placeId);
    setDescription(description);
    if (cartData?.length !== 0) {
      onOpenModal("locationConfirmation");
    } else {
      handlePredictionAfterConfirmation(placeId);
    }
  };
  const handlePredictionAfterConfirmation = (placeId: any) => {
    dispatch(setAddressType(""));

    setInputValue(description); // Set the selected input value
    setPredictions([]); // Clear the dropdown

    const placesService = new window.google.maps.places.PlacesService(
      document.createElement("div")
    );

    // Get more details about the selected place using the placeId
    try {
      placesService.getDetails(
        {
          placeId,
          sessionToken: sessionTokenRef.current || undefined,
          fields: [
            "geometry",
            "formatted_address",
            "name",
            "address_component",
          ],
        },
        (
          place: google.maps.places.PlaceResult | null,
          status: google.maps.places.PlacesServiceStatus
        ) => {
          if (status === google.maps.places.PlacesServiceStatus.OK && place) {
            // Dispatch location to Redux store
            if (place?.geometry?.location) {
              onSelectLocation(place);
              dispatch(
                setUserLocation({
                  error: null,
                  display_name:
                    place.formatted_address || place.name || "Unknown place",
                  latitude: place.geometry.location.lat(),
                  longitude: place.geometry.location.lng(),
                })
              );
              let payload: any = {
                latitude: place.geometry.location.lat(),
                longitude: place.geometry.location.lng(),
              };
              const aId = localStorage.getItem("aId");
              const accessToken = getDecryptedToken();

              if (aId && accessToken == null) {
                payload.anonymous_id = aId;
              }
              dispatch(setLocationAsync(payload))
                .then((response: any) => {
                  if (response?.payload?.data?.location?.anonymous_id) {
                    localStorage.setItem(
                      "aId",
                      response?.payload?.data?.location?.anonymous_id
                    );
                  }
                  if (response?.payload?.data?.location) {
                    dispatch(setLocationVerifiedStatus("success"));
                    // Create a new session token after successful selection
                    sessionTokenRef.current =
                      new window.google.maps.places.AutocompleteSessionToken();
                    window.location.href = "/";
                    onCloseModal();
                    dispatch(
                      showSnackbar({
                        message: "Location added successfully",
                        severity: "success",
                        autoHide: 3000,
                      })
                    );
                    onCloseModal();
                  } else {
                    dispatch(
                      showSnackbar({
                        message: "Please try again later.",
                        severity: "error",
                        autoHide: 3000,
                      })
                    );
                  }
                })
                .catch((error) => {
                  console.error("Error setting location:", error);
                  dispatch(
                    showSnackbar({
                      message: "Error setting location. Please try again.",
                      severity: "error",
                      autoHide: 3000,
                    })
                  );
                });
            }
          } else if (status !== google.maps.places.PlacesServiceStatus.OK) {
            console.error("Places Service error:", status);
            dispatch(
              showSnackbar({
                message:
                  "Error fetching place details. Please try again later.",
                severity: "error",
                autoHide: 3000,
              })
            );
          }
        }
      );
    } catch (error) {
      console.error("Error getting place details:", error);
      dispatch(
        showSnackbar({
          message: "Error fetching place details. Please try again.",
          severity: "error",
          autoHide: 3000,
        })
      );
    }
  };
  const promptClose = () => {
    setModalType("");
  };
  return (
    <>
      <Box sx={{ position: "relative", width: "100%" }}>
        <TextField
          inputRef={inputRef}
          value={inputValue}
          onChange={handleInputChange}
          label="Search Location"
          placeholder="Search Location"
          variant="outlined"
          fullWidth
          size="small"
        />

        {/* Display predictions in a dropdown */}
        {predictions?.length > 0 && (
          <List
            sx={{
              position: "absolute",
              zIndex: 1000,
              top: "100%",
              left: 0,
              right: 0,
              backgroundColor: "white",
              border: "1px solid #ccc",
              borderRadius: "4px",
              maxHeight: "200px",
              overflowY: "auto",
            }}
          >
            {predictions?.map((prediction) => (
              <ListItem
                sx={{
                  // borderBorrom: "1px solid #ccc",
                  cursor: "pointer",
                }}
                key={prediction.place_id}
                // button
                onClick={() =>
                  handlePredictionClick(
                    prediction.place_id,
                    prediction.description
                  )
                }
              >
                <span style={{ marginRight: 10 }}>
                  {" "}
                  <LocationOnIcon color="error" fontSize="small" />
                </span>
                {prediction.description}
              </ListItem>
            ))}
          </List>
        )}
      </Box>
      <CustomDialog
        component={
          <LocationConfirmationPrompt
            onClose={promptClose}
            onModalCloseCallback={onModalCloseCallback}
            isFromCheckout={false}
          />
        }
        title=""
        openDialog={modalType === "locationConfirmation"}
        handleCloseDialog={promptClose}
        modalPlace="center"
      />
    </>
  );
};

export default GoogleLocationSearch;
