import React, { forwardRef, memo, useEffect, useState } from 'react';
import {
  Input,
  Box,
  InputProps,
  PopoverAnchor,
  Popover,
  PopoverContent,
  PopoverBody,
  List,
  ListItem,
} from '@chakra-ui/react';
import { withYMaps } from '@pbe/react-yandex-maps';
import { useTranslation } from 'react-i18next';

import { Suggestion } from '../types';
import { isValidLocation } from '../helper';

import {
  formatLocation,
  getLocationByAddress,
  isRealLocation,
  extractAddress,
} from './helper';
import { LocationInputProps } from './types';

export const LocationInput = memo(
  withYMaps(
    forwardRef<HTMLInputElement, LocationInputProps>(function LocationInput(
      { ymaps, value, onChange, ...props },
      ref,
    ) {
      const [inputValue, setInputValue] = useState<string>('');

      useEffect(() => {
        setInputValue(value);
      }, [value]);

      const [suggestions, setSuggestions] = useState<Suggestion[]>([]);
      const [isSuggestionsPanelOpen, setIsSuggestionsPanelOpen] =
        useState<boolean>(false);

      const onInputChange: InputProps['onChange'] = async (e) => {
        const newInputValue = e.target.value;
        setInputValue(newInputValue);

        if (newInputValue.trim().length > 3) {
          try {
            const address = extractAddress(newInputValue);
            const results = await ymaps.suggest(address);
            setSuggestions(results);
          } catch (error) {
            console.error(error);
          }
        } else {
          setSuggestions([]);
        }

        setIsSuggestionsPanelOpen(suggestions.length > 1);
      };

      const onFocus: InputProps['onFocus'] = () => {
        setIsSuggestionsPanelOpen(suggestions.length > 1);
      };

      const onBlur: InputProps['onBlur'] = async (e) => {
        const inputValue = e.target.value;
        if (
          isValidLocation(inputValue) &&
          (await isRealLocation(ymaps, inputValue))
        ) {
          onChange(inputValue);
        } else {
          setInputValue(value);
        }
        setIsSuggestionsPanelOpen(false);
      };

      const handleSuggestionClick = async ({ value: address }: Suggestion) => {
        try {
          const location = await getLocationByAddress(ymaps, address);
          const newValue = formatLocation(location);
          setInputValue(newValue);
          onChange(newValue);
        } catch (error) {
          console.error(error);          
        }
      };

      const { t } = useTranslation('~', {
        keyPrefix: 'dry-wash.order-create.form.washing-location-field',
      });

      return (
        <Box width='100%'>
          <Popover
            isOpen={isSuggestionsPanelOpen}
            autoFocus={false}
            placement='bottom-start'
          >
            <PopoverAnchor>
              <Input
                {...props}
                ref={ref}
                onBlur={onBlur}
                value={inputValue}
                onChange={onInputChange}
                onFocus={onFocus}
                placeholder={t('placeholder')}
              />
            </PopoverAnchor>
            <PopoverContent width='100%' maxWidth='100%'>
              <PopoverBody border='1px' borderColor='gray.300' p={0}>
                <List>
                  {suggestions.map((suggestion, index) => (
                    <ListItem
                      key={index}
                      p={2}
                      cursor='pointer'
                      _hover={{
                        bgColor: 'primary.50',
                      }}
                      _active={{
                        bgColor: 'primary.100',
                      }}
                      onClick={() => handleSuggestionClick(suggestion)}
                    >
                      {suggestion.displayName}
                    </ListItem>
                  ))}
                </List>
              </PopoverBody>
            </PopoverContent>
          </Popover>
        </Box>
      );
    }),
    true,
    ['suggest', 'geocode'],
  ),
);

// todo: i18n
// todo: replace console.error with toast
