import {
  ActivityIndicator,
  FlatList,
  ScrollView,
  StyleSheet,
  TouchableOpacity,
  View,
} from 'react-native';
import { ThemeText } from '../../../../functions/CustomElements';
import { CENTER } from '../../../../constants/styles';
import { INSET_WINDOW_WIDTH } from '../../../../constants/theme';
import GetThemeColors from '../../../../hooks/themeColors';
import {
  COLORS,
  CONTENT_KEYBOARD_OFFSET,
  EMAIL_REGEX,
  SIZES,
  VALID_URL_REGEX,
  VALID_USERNAME_REGEX,
} from '../../../../constants';
import { useGlobalContactsInfo } from '../../../../../context-store/globalContacts';
import useDebounce from '../../../../hooks/useDebounce';
import { useCallback, useEffect, useRef, useState } from 'react';
import { useFocusEffect, useNavigation } from '@react-navigation/native';
import { searchUsers } from '../../../../../db';
import CustomButton from '../../../../functions/CustomElements/button';
import CustomSearchInput from '../../../../functions/CustomElements/searchInput';
import customUUID from '../../../../functions/customUUID';
import { useKeysContext } from '../../../../../context-store/keys';
import { keyboardNavigate } from '../../../../functions/customNavigation';
import { useGlobalThemeContext } from '../../../../../context-store/theme';
import ContactProfileImage from './internalComponents/profileImage';
import { getCachedProfileImage } from '../../../../functions/cachedImage';
import { useImageCache } from '../../../../../context-store/imageCache';
import { useTranslation } from 'react-i18next';
import getDeepLinkUser from './internalComponents/getDeepLinkUser';
import { isBlitzLNURLAddress } from '../../../../functions/lnurl';
import getPhonePaymentAddress, {
  isPhonePaymentNumber,
} from '../../../../functions/sendBitcoin/getPhonePaymentAddress';
import ThemeIcon from '../../../../functions/CustomElements/themeIcon';
import FullLoadingScreen from '../../../../functions/CustomElements/loadingScreen';

export default function AddContactsHalfModal({
  slideHeight,
  setIsKeyboardActive,
  startingSearchValue,
  handleBackPressFunction,
  isScreenActive,
}) {
  return (
    <AddContactContent
      setIsKeyboardActive={setIsKeyboardActive}
      startingSearchValue={startingSearchValue}
      handleBackPressFunction={handleBackPressFunction}
      onContactAdded={null}
      isScreenActive={isScreenActive}
    />
  );
}

export function AddContactContent({
  setIsKeyboardActive,
  startingSearchValue,
  handleBackPressFunction,
  onContactAdded,
  isScreenActive,
}) {
  const { contactsPrivateKey } = useKeysContext();
  const { theme, darkModeType } = useGlobalThemeContext();
  const { globalContactsInformation } = useGlobalContactsInfo();
  const [searchInput, setSearchInput] = useState(startingSearchValue || '');
  const [users, setUsers] = useState([]);
  const [isSearching, setIsSearching] = useState(false);
  const [remoteLoadingMessage, setRemoteLoadingMessage] = useState('');
  const navigate = useNavigation();
  const { refreshCacheObject } = useImageCache();
  const searchTrackerRef = useRef(null);
  const searchCacheRef = useRef(new Map()); // normalizedTerm -> resolved users[]
  const didClickCamera = useRef(null);
  const { t } = useTranslation();
  const isFocused = useRef(false);

  const isUsingLNURL =
    searchInput?.includes('@') && searchInput?.indexOf('@') !== 0;
  const isPhoneNumber = isPhonePaymentNumber(searchInput);

  useEffect(() => {
    isFocused.current = true;
    if (startingSearchValue) {
      handleSearch(startingSearchValue);
    }
    return () => {
      isFocused.current = false;
    };
  }, []);

  const handleSearchTrackerRef = () => {
    const requestUUID = customUUID();
    searchTrackerRef.current = requestUUID; // Simply store the latest UUID
    return requestUUID;
  };

  const getSearchCacheKey = term => term.replace(/@/g, '').trim().toLowerCase();

  const handleTextInputBlur = () => {
    if (setIsKeyboardActive) setIsKeyboardActive(false);
    if (!searchInput && !didClickCamera.current) {
      handleBackPressFunction?.();
    }
    didClickCamera.current = false;
  };

  const debouncedSearch = useDebounce(async (term, requestUUID) => {
    // Block request if user has moved on
    if (searchTrackerRef.current !== requestUUID) {
      return;
    }

    const searchTerm = term.replace(/@/g, '');
    if (searchTerm) {
      const results = await searchUsers(searchTerm);
      const newUsers = (
        await Promise.all(
          results.map(async savedContact => {
            if (!savedContact) return false;
            const uniqueName = savedContact?.uniqueName;
            const contactUUID = savedContact?.uuid;
            const hasProfileImage = savedContact?.hasProfileImage;
            if (uniqueName === globalContactsInformation.myProfile.uniqueName)
              return false;
            if (!contactUUID) return false;

            let responseData;

            if (hasProfileImage || typeof hasProfileImage === 'boolean') {
              responseData = await getCachedProfileImage(contactUUID);
              console.log(responseData, 'response');
            }

            if (!responseData) return savedContact;
            else
              return {
                ...savedContact,
                ...responseData,
              };
          }),
        )
      ).filter(Boolean);

      refreshCacheObject();
      searchCacheRef.current.set(getSearchCacheKey(term), newUsers);
      setIsSearching(false);
      setUsers(newUsers);
    } else {
      setIsSearching(false);
    }
  }, 450);

  const handleSearch = term => {
    setSearchInput(term);
    handleSearchTrackerRef();
    if (isUsingLNURL) {
      searchTrackerRef.current = null;
      setIsSearching(false);
      return;
    }

    if (isPhonePaymentNumber(term)) {
      searchTrackerRef.current = null;
      setUsers([]);
      setIsSearching(false);
      return;
    }

    if (term.length === 0 || term === '@') {
      searchTrackerRef.current = null;
      setUsers([]);
      setIsSearching(false);
      return;
    }

    const cacheKey = getSearchCacheKey(term);
    if (cacheKey && searchCacheRef.current.has(cacheKey)) {
      searchTrackerRef.current = null; // cancel any in-flight/pending search
      setUsers(searchCacheRef.current.get(cacheKey));
      setIsSearching(false);
      return;
    }

    if (term.length > 0) {
      const requestUUID = handleSearchTrackerRef();
      setIsSearching(true);
      debouncedSearch(term, requestUUID);
    }
  };

  const resolveBlitzLNURLContact = async address => {
    const username = address.split('@')[0];
    return await getDeepLinkUser({
      deepLinkContent: `blitz-wallet/u/${username}`,
      userProfile: globalContactsInformation.myProfile,
    });
  };

  const parseContact = async data => {
    try {
      const sanitizedData = data.trim();
      setIsSearching(true);
      setRemoteLoadingMessage(
        t('contacts.addContactsHalfModal.loadingMessage'),
      );
      let newContact;
      if (isBlitzLNURLAddress(sanitizedData)) {
        const {
          didWork,
          reason,
          data: userProfile,
        } = await resolveBlitzLNURLContact(sanitizedData);

        if (!didWork) {
          navigate.navigate('ErrorScreen', {
            errorMessage: t(reason),
          });
          return;
        }
        newContact = userProfile;
      } else if (VALID_URL_REGEX.test(sanitizedData)) {
        const {
          didWork,
          reason,
          data: userProfile,
        } = await getDeepLinkUser({
          deepLinkContent: sanitizedData,
          userProfile: globalContactsInformation.myProfile,
        });

        if (!didWork) {
          navigate.navigate('ErrorScreen', {
            errorMessage: t(reason),
          });
          return;
        }
        newContact = userProfile;
      } else {
        const decoded = atob(sanitizedData);
        const parsedData = JSON.parse(decoded);
        const {
          didWork,
          reason,
          data: userProfile,
        } = await getDeepLinkUser({
          deepLinkContent: `blitz-wallet/u/${parsedData.uniqueName}`,
          userProfile: globalContactsInformation.myProfile,
        });

        if (!didWork) {
          navigate.navigate('ErrorScreen', {
            errorMessage: t(reason),
          });
          return;
        }
        newContact = userProfile;
      }

      setRemoteLoadingMessage(t('contacts.addContactsHalfModal.profileImage'));
      await getCachedProfileImage(newContact.uuid);

      if (!isFocused.current) {
        console.log('Page is not focused, do not navigate');
        return;
      }
      if (onContactAdded) {
        onContactAdded(newContact);
      } else {
        navigate.replace('ExpandedAddContactsPage', { newContact: newContact });
      }
    } catch (err) {
      setIsSearching(false);
      console.log('parse contact half modal error', err);
      navigate.navigate('ErrorScreen', {
        errorMessage: t('contacts.addContactsHalfModal.noContactsMessage'),
      });
    } finally {
      setIsSearching(false);
      setRemoteLoadingMessage('');
    }
  };

  const clearHalfModalForLNURL = async () => {
    if (!EMAIL_REGEX.test(searchInput)) return;

    if (isBlitzLNURLAddress(searchInput)) {
      setIsSearching(true);
      setRemoteLoadingMessage(
        t('contacts.addContactsHalfModal.loadingMessage'),
      );
      try {
        const {
          didWork,
          reason,
          data: userProfile,
        } = await resolveBlitzLNURLContact(searchInput);

        if (!didWork) {
          navigate.navigate('ErrorScreen', { errorMessage: t(reason) });
          return;
        }

        setRemoteLoadingMessage(
          t('contacts.addContactsHalfModal.profileImage'),
        );
        await getCachedProfileImage(userProfile.uuid);

        if (!isFocused.current) return;

        if (onContactAdded) {
          onContactAdded(userProfile);
        } else {
          handleBackPressFunction(() => {
            navigate.replace('ExpandedAddContactsPage', {
              newContact: userProfile,
            });
          });
        }
      } catch (err) {
        console.log('clearHalfModalForLNURL blitz error', err);
        navigate.navigate('ErrorScreen', {
          errorMessage: t('contacts.addContactsHalfModal.noContactsMessage'),
        });
      } finally {
        setIsSearching(false);
        setRemoteLoadingMessage('');
      }
      return;
    }
    setRemoteLoadingMessage(t('contacts.addContactsHalfModal.loadingMessage'));

    const newContact = {
      name: searchInput.split('@')[0],
      bio: '',
      uniqueName: '',
      isFavorite: false,
      transactions: [],
      unlookedTransactions: 0,
      receiveAddress: searchInput,
      isAdded: true,
      isLNURL: true,
      profileImage: '',
      uuid: customUUID(),
    };

    if (onContactAdded) {
      onContactAdded(newContact);
    } else {
      handleBackPressFunction(() => {
        navigate.replace('ExpandedAddContactsPage', {
          newContact: newContact,
        });
      });
    }
  };

  const clearHalfModalForPhone = async () => {
    setIsSearching(true);
    setRemoteLoadingMessage(t('contacts.addContactsHalfModal.loadingMessage'));
    try {
      const enteredNumber = searchInput.trim();
      const receiveAddress = await getPhonePaymentAddress(enteredNumber);

      if (!receiveAddress) {
        navigate.navigate('ErrorScreen', {
          errorMessage: t('contacts.addContactsHalfModal.noContactsMessage'),
        });
        return;
      }

      const newContact = {
        name: enteredNumber,
        bio: '',
        uniqueName: '',
        isFavorite: false,
        transactions: [],
        unlookedTransactions: 0,
        receiveAddress,
        isAdded: true,
        isLNURL: true,
        profileImage: '',
        uuid: customUUID(),
      };

      if (!isFocused.current) return;

      if (onContactAdded) {
        onContactAdded(newContact);
      } else {
        handleBackPressFunction(() => {
          navigate.replace('ExpandedAddContactsPage', {
            newContact: newContact,
          });
        });
      }
    } catch (err) {
      console.log('clearHalfModalForPhone error', err);
      navigate.navigate('ErrorScreen', {
        errorMessage: t('contacts.addContactsHalfModal.noContactsMessage'),
      });
    } finally {
      setIsSearching(false);
      setRemoteLoadingMessage('');
    }
  };

  const handleAddPress = () => {
    if (isPhoneNumber) {
      clearHalfModalForPhone();
    } else {
      clearHalfModalForLNURL();
    }
  };

  if (remoteLoadingMessage.length) {
    return (
      <FullLoadingScreen
        textStyles={{ textAlign: 'center' }}
        text={remoteLoadingMessage}
      />
    );
  }

  return (
    <View style={styles.innerContainer}>
      <View style={styles.titleContainer}>
        <ThemeText
          styles={styles.titleText}
          content={t('contacts.addContactsHalfModal.title')}
        />
        {isSearching && (
          <ActivityIndicator
            size={'small'}
            color={theme && darkModeType ? COLORS.darkModeText : COLORS.primary}
          />
        )}
      </View>
      <CustomSearchInput
        placeholderText={t('contacts.addContactsHalfModal.searchPlaceholder')}
        setInputText={handleSearch}
        inputText={searchInput}
        autoFocus={true}
        blurOnSubmit={false}
        containerStyles={{
          justifyContent: 'center',
          marginBottom: CONTENT_KEYBOARD_OFFSET,
        }}
        textInputStyles={{ paddingRight: 45 }}
        onSubmitEditingFunction={handleAddPress}
        buttonComponent={
          <TouchableOpacity
            onPress={() => {
              didClickCamera.current = true;
              if (isScreenActive) isScreenActive.current = false;
              keyboardNavigate(() =>
                navigate.navigate('CameraModal', {
                  updateBitcoinAdressFunc: parseContact,
                  fromPage: 'addContact',
                }),
              );
            }}
            style={{
              position: 'absolute',
              right: 10,
              zIndex: 1,
            }}
          >
            <ThemeIcon
              colorOverride={
                theme && darkModeType ? COLORS.lightModeText : COLORS.primary
              }
              iconName={'ScanLine'}
            />
          </TouchableOpacity>
        }
        onFocusFunction={() => setIsKeyboardActive && setIsKeyboardActive(true)}
        onBlurFunction={handleTextInputBlur}
      />

      {isUsingLNURL || isPhoneNumber ? (
        <ScrollView
          keyboardShouldPersistTaps="always"
          showsVerticalScrollIndicator={false}
          contentContainerStyle={{
            alignItems: 'center',
            marginTop: 10,
            flexGrow: 1,
          }}
        >
          <ThemeText
            content={t('contacts.addContactsHalfModal.lnurlAddMessage')}
          />
          <ThemeText styles={{ marginBottom: 25 }} content={searchInput} />

          <CustomButton
            buttonStyles={{
              width: 'auto',
              ...CENTER,
              marginTop: 'auto',
            }}
            actionFunction={handleAddPress}
            textContent={t('constants.continue')}
          />
        </ScrollView>
      ) : (
        <>
          {users.length ? (
            <FlatList
              showsVerticalScrollIndicator={false}
              data={users}
              renderItem={({ item }) => (
                <ContactListItem
                  savedContact={item}
                  contactsPrivateKey={contactsPrivateKey}
                  theme={theme}
                  darkModeType={darkModeType}
                  onContactAdded={onContactAdded}
                  handleBackPressFunction={handleBackPressFunction}
                />
              )}
              keyExtractor={item => item?.uniqueName}
              keyboardShouldPersistTaps="handled"
              keyboardDismissMode="none"
            />
          ) : (
            <ThemeText
              styles={{ textAlign: 'center', marginTop: 10 }}
              content={
                isSearching && searchInput.length > 0
                  ? ''
                  : searchInput.length > 0 && searchInput !== '@'
                  ? t('contacts.addContactsHalfModal.noProfilesFound')
                  : t('contacts.addContactsHalfModal.startTypingMessage')
              }
            />
          )}
        </>
      )}
    </View>
  );
}
function ContactListItem({
  savedContact,
  onContactAdded,
  handleBackPressFunction,
  darkModeType,
  theme,
}) {
  const { textColor, backgroundOffset } = GetThemeColors();
  const navigate = useNavigation();

  const newContact = {
    ...savedContact,
    isFavorite: false,
    transactions: [],
    unlookedTransactions: 0,
    isAdded: true,
  };

  const handleContactPress = () => {
    if (onContactAdded) {
      onContactAdded(newContact);
    } else {
      handleBackPressFunction(() => {
        navigate.replace('ExpandedAddContactsPage', {
          newContact: newContact,
        });
      });
    }
  };

  return (
    <TouchableOpacity onPress={handleContactPress}>
      <View style={[styles.contactListContainer, {}]}>
        <View
          style={[
            styles.contactListLetterImage,
            {
              backgroundColor: backgroundOffset,
            },
          ]}
        >
          <ContactProfileImage
            updated={newContact.updated}
            uri={newContact.localUri}
            darkModeType={darkModeType}
            theme={theme}
          />
        </View>
        <View>
          <ThemeText
            styles={{ includeFontPadding: false }}
            content={newContact.uniqueName}
          />
          <ThemeText
            styles={{ includeFontPadding: false, fontSize: SIZES.small }}
            content={newContact.name || 'No name set'}
          />
        </View>
      </View>
    </TouchableOpacity>
  );
}

const styles = StyleSheet.create({
  innerContainer: { flex: 1, width: INSET_WINDOW_WIDTH, ...CENTER },

  titleContainer: {
    alignItems: 'center',
    marginBottom: 10,
    flexDirection: 'row',
  },

  titleText: {
    fontSize: SIZES.large,
    fontWeight: '500',
    textAlign: 'left',
    marginRight: 10,
  },

  contactListContainer: {
    width: '100%',
    paddingVertical: 10,

    flexDirection: 'row',
    alignItems: 'center',
  },

  contactListLetterImage: {
    height: 40,
    width: 40,
    borderRadius: 20,
    alignItems: 'center',
    justifyContent: 'center',
    overflow: 'hidden',
    marginRight: 10,
  },
});
