import React, { FC, ReactNode, useState } from 'react';
import {
  TextInput,
  Text,
  View,
  InputModeOptions,
  NativeSyntheticEvent,
  TextInputFocusEventData,
  TouchableOpacity,
  Linking,
  Platform
} from 'react-native';
import { styling } from './style';
import { Colors } from 'src/theme';
import { GOOGLE_MAP_PLACES_APIKEY } from 'src/constants';

type Props = {
  placeholder?: string;
  onChange?: (text: string) => void;
  header?: string;
  isPrivate?: boolean;
  inputMode?: InputModeOptions;
  isFocused?: (boolean: boolean) => void;
  value?: string;
  active?: boolean;
  onBlur?: (e: NativeSyntheticEvent<TextInputFocusEventData>) => void;
  formikError?: string | boolean;
  icon?: ReactNode;
  multiline?: boolean;
  editable?: boolean;
  height?: number;
  backgroundColor?: string;
  clearIcon?: ReactNode;
  setValue?: (value: string) => void;
  autoFocus?: boolean;
};

const parseTextWithLinks = (text?: string): React.ReactNode => {
  if (!text) return null;

  const urlRegex = /((https?:\/\/[^\s]+)|(?<!\w)(www\.[^\s]+))/g;

  const result: React.ReactNode[] = [];
  let lastIndex = 0;

  Array.from(text.matchAll(urlRegex)).forEach((match, index) => {
    const matchText = match[0];
    const matchIndex = match.index ?? 0;

    if (matchIndex < lastIndex) return;

    if (lastIndex < matchIndex) {
      result.push(<Text key={`text-${index}`}>{text.slice(lastIndex, matchIndex)}</Text>);
    }

    let url = matchText.startsWith('http') ? matchText : `https://${matchText}`;
    const isGoogleMaps = /google\.com\/maps|maps\.google\.com/.test(url);

    const handlePress = async () => {
      if (isGoogleMaps) {
        const latLngMatch = url.match(/@(-?\d+\.\d+),(-?\d+\.\d+)/);
        const lat = latLngMatch?.[1];
        const lng = latLngMatch?.[2];

        let mapsUrl = url;

        if (Platform.OS === 'ios') {
          mapsUrl = lat && lng ? `comgooglemaps://?q=${lat},${lng}` : url;
        } else {
          mapsUrl = lat && lng ? `geo:${lat},${lng}?q=${lat},${lng}` : url;
        }

        const supported = await Linking.canOpenURL(mapsUrl);
        if (supported) {
          await Linking.openURL(mapsUrl);
        } else {
          await Linking.openURL(url);
        }
      } else {
        await Linking.openURL(url);
      }
    };

    result.push(
      <Text
        key={`link-${index}`}
        style={{ color: Colors.ORANGE, textDecorationLine: 'none' }}
        onPress={handlePress}
      >
        {matchText}
      </Text>
    );

    lastIndex = matchIndex + matchText.length;
  });

  if (lastIndex < text.length) {
    result.push(<Text key="text-end">{text.slice(lastIndex)}</Text>);
  }

  return result;
};

export const Input: FC<Props> = ({
  onChange,
  placeholder,
  header,
  isPrivate,
  inputMode,
  isFocused,
  onBlur,
  value,
  formikError,
  icon,
  multiline,
  editable,
  height,
  backgroundColor = Colors.FILL_LIGHT,
  clearIcon,
  setValue,
  autoFocus
}) => {
  const [focused, setFocused] = useState(false);

  const styles = styling(focused);

  return (
    <View>
      {header ? <Text style={styles.text}>{header}</Text> : null}
      <View
        style={[
          [styles.wrapper, formikError ? styles.inputError : null, { backgroundColor }],
          { flexDirection: 'row', alignItems: 'center' },
          multiline ? { minHeight: height ?? 100, height: 'auto' } : { height: height ?? 44 }
        ]}
      >
        {icon ? (
          <View
            style={{
              height: 44,
              width: 44,
              display: 'flex',
              justifyContent: 'center',
              alignItems: 'center'
            }}
          >
            {icon}
          </View>
        ) : null}
        {editable === false ? (
          <Text
            style={[
              {
                width: '100%',
                flex: 1
              },
              !icon ? { padding: 10 } : null
            ]}
          >
            {parseTextWithLinks(value)}
          </Text>
        ) : (
          <TextInput
            editable={editable}
            value={value}
            inputMode={inputMode ?? 'text'}
            secureTextEntry={isPrivate ?? false}
            placeholder={placeholder}
            placeholderTextColor={Colors.LIGHT_GRAY}
            onChangeText={onChange}
            multiline={multiline}
            contextMenuHidden={inputMode === 'none'}
            caretHidden={inputMode === 'none'}
            onPress={() => {
              setFocused(true);
              if (isFocused) {
                isFocused(true);
              }
            }}
            onFocus={() => {
              if (inputMode !== 'none') {
                setFocused(true);
                if (isFocused) {
                  isFocused(true);
                }
              }
            }}
            onBlur={(e) => {
              setFocused(false);
              if (onBlur) {
                onBlur(e);
              }
            }}
            style={[
              { height: '100%', width: '100%', flex: 1, color: Colors.BLACK },
              !icon ? { padding: 10 } : null
            ]}
            autoFocus={autoFocus}
          />
        )}
        {clearIcon && value && value?.length > 0 ? (
          <TouchableOpacity
            style={styles.clearIcon}
            onPress={() => {
              setValue && setValue('');
            }}
          >
            {clearIcon}
          </TouchableOpacity>
        ) : null}
      </View>
      {formikError ? <Text style={styles.errorText}>{formikError}</Text> : null}
    </View>
  );
};
