import React, { useEffect, useRef, useState, useCallback } from 'react';
import {
  ActivityIndicator,
  StyleSheet,
  View,
  Text,
  Alert,
  Modal,
  Animated,
  Easing,
  TouchableWithoutFeedback,
  Platform,
  Dimensions,
} from 'react-native';
import type { CryptoWalletProps } from './types/crypto_wallet_props';
import WebView, { type WebViewNavigation } from 'react-native-webview';
import CryptoWalletInit from './CryptoWalletInit';
import { colors } from './configs';

const borderRadiusDimension = 24 / 896;
const windowHeight = Dimensions.get('window').height;

const CryptoWallet: React.FC<CryptoWalletProps> = ({
  apiKey,
  customerEmail,
  callbackUrl,
  businessName,
  bussinessLogo,
  activityIndicatorColor = colors.primary,
}) => {
  const [_, setLoading] = useState(true);
  const [error, setError] = useState('');
  const [url, setUrl] = useState<string | null>(null);
  const [showModal, setshowModal] = useState(false);
  const webViewRef = useRef<WebView | null>(null);
  const animation = useRef<Animated.Value>(new Animated.Value(0));

  const animateIn = React.useCallback(() => {
    setshowModal(true);
    Animated.timing(animation.current, {
      toValue: 1,
      duration: 700,
      easing: Easing.in(Easing.elastic(0.72)),
      useNativeDriver: false,
    }).start();
  }, []);

  const animateOut = React.useCallback((): Promise<void> => {
    return new Promise((resolve) => {
      Animated.timing(animation.current, {
        toValue: 0,
        duration: 400,
        useNativeDriver: false,
      }).start(() => {
        setshowModal(false);
        resolve();
      });
    });
  }, []);

  const onReload = React.useCallback(() => {
    if (webViewRef.current) {
      webViewRef.current.reload();
    }
  }, []);

  const onCancel = useCallback(
    (confirmed: boolean = false) => {
      if (!confirmed) {
        Alert.alert('', 'Are you sure you want to cancel this payment?', [
          { text: 'No' },
          {
            text: 'Yes, Cancel',
            style: 'destructive',
            onPress: () => onCancel(true),
          },
        ]);
        return;
      }
      // remove tx_ref and dismiss
      animateOut();
    },
    [animateOut]
  );

  useEffect(() => {
    setLoading(true);
    animateIn();
    CryptoWalletInit({
      apiKey: apiKey,
      customer_email: customerEmail,
      business_name: businessName,
      business_logo: bussinessLogo,
      callback_url: callbackUrl,
    })
      .then((response) => {
        console.log(response);
        setLoading(false);
        setUrl(response);
        setError('');
      })
      .catch((error) => {
        console.log(error);
        setLoading(false);
        setError((error as Error).message);
      });
  }, [false]);

  const marginTop = animation.current.interpolate({
    inputRange: [0, 1],
    outputRange: [windowHeight, 0],
  });
  const opacity = animation.current.interpolate({
    inputRange: [0, 0.3, 1],
    outputRange: [0, 1, 1],
  });

  return (
    <Modal
      style={{ flex: 1 }}
      visible={showModal}
      hardwareAccelerated={false}
      animationType="slide"
      transparent={true}
    >
      <CryptoWalletBackdrop
        onPress={() => onCancel()}
        animation={animation.current}
      />
      <Animated.View style={[styles.container, { marginTop, opacity }]}>
        {error && (
          <CryptoWalletError error={error} onTryAgain={() => onReload()} />
        )}
        <WebView
          source={{ uri: url || '' }}
          cacheEnabled={false}
          cacheMode={'LOAD_NO_CACHE'}
          ref={webViewRef}
          style={styles.webView}
          renderLoading={() => (
            <ActivityIndicator
              size="large"
              style={styles.progressBar}
              color={activityIndicatorColor}
            />
          )}
          renderError={() => (
            <CryptoWalletError error={''} onTryAgain={() => onReload()} />
          )}
          onNavigationStateChange={(state: WebViewNavigation) => {
            console.log(state);
          }}
        />
      </Animated.View>
    </Modal>
  );
};

interface CryptoWalletBackdropProps {
  animation: Animated.Value;
  onPress?: () => void;
}

const CryptoWalletBackdrop: React.FC<CryptoWalletBackdropProps> = ({
  animation,
  onPress,
}) => {
  // Interpolation backdrop animation
  const backgroundColor = animation.interpolate({
    inputRange: [0, 0.3, 1],
    outputRange: [colors.transparent, colors.transparent, 'rgba(0,0,0,0.5)'],
  });
  return (
    <TouchableWithoutFeedback testID="flw-checkout-backdrop" onPress={onPress}>
      <Animated.View
        style={Object.assign({}, styles.backdrop, { backgroundColor })}
      />
    </TouchableWithoutFeedback>
  );
};

type CryptoWalletErrorProps = {
  error?: string;
  onTryAgain: () => void;
};
const CryptoWalletError: React.FC<CryptoWalletErrorProps> = ({}) => {
  return (
    <View style={styles.error}>
      <Text style={styles.errorText}>
        An error occur, Please close the dialog and try again
      </Text>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    top: Platform.select({ ios: 96, android: 64 }),
    flex: 1,
    backgroundColor: '#efefef',
    paddingBottom: Platform.select({ ios: 96, android: 64 }),
    overflow: 'hidden',
    borderTopLeftRadius: windowHeight * borderRadiusDimension,
    borderTopRightRadius: windowHeight * borderRadiusDimension,
  },
  progressBar: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  webView: {
    flex: 1,
    backgroundColor: 'rgba(0,0,0,0)',
  },
  error: {
    flex: 1,
    justifyContent: 'center',
  },
  errorText: {
    textAlign: 'center',
    fontSize: 20,
    margin: 40,
    paddingHorizontal: 50,
  },
  errorButton: {
    padding: 12,
    backgroundColor: 'blue',
    marginHorizontal: 40,
    borderRadius: 50,
  },
  errorButtonText: {
    textAlign: 'center',
    fontSize: 18,
    color: 'white',
  },
  backdrop: {
    position: 'absolute',
    left: 0,
    right: 0,
    bottom: 0,
    top: 0,
  },
});

export default CryptoWallet;
