import React, { useEffect, useState } from 'react';
import { Alert, Image, View } from 'react-native';
import { ActivityIndicator, Button, Text } from 'react-native-paper';

import { useNavigation } from '@react-navigation/native';
import {
  NativeStackNavigationProp,
  NativeStackScreenProps,
} from '@react-navigation/native-stack';

import { Account, StackParamsList } from '../types';
import AccountDetails from './AccountDetails';
import styles from '../styles/stylesheet';
import { signMessage } from '../utils/sign-message';
import { retrieveSingleAccount } from '../utils/accounts';
import {
  approveWalletConnectRequest,
  rejectEIP155Request,
} from '../utils/wallet-connect/WalletConnectRequests';
import { web3wallet } from '../utils/wallet-connect/WalletConnectUtils';
import { useWalletConnect } from '../context/WalletConnectContext';

type SignRequestProps = NativeStackScreenProps<StackParamsList, 'SignRequest'>;

const SignRequest = ({ route }: SignRequestProps) => {
  const { requestSession } = useWalletConnect();

  const requestName = requestSession?.peer?.metadata?.name;
  const requestIcon = requestSession?.peer?.metadata?.icons[0];
  const requestURL = requestSession?.peer?.metadata?.url;

  const [account, setAccount] = useState<Account>();
  const [message, setMessage] = useState<string>('');
  const [network, setNetwork] = useState<string>('');
  const [isLoading, setIsLoading] = useState(true);

  const navigation =
    useNavigation<NativeStackNavigationProp<StackParamsList>>();

  const retrieveData = async (
    requestNetwork: string,
    requestAddress: string,
    requestMessage: string,
  ) => {
    const requestAccount = await retrieveSingleAccount(
      requestNetwork,
      requestAddress,
    );
    if (!requestAccount) {
      navigation.navigate('InvalidPath');
      return;
    }

    if (requestAccount !== account) {
      setAccount(requestAccount);
    }
    if (requestMessage !== message) {
      setMessage(decodeURIComponent(requestMessage));
    }
    if (requestNetwork !== network) {
      setNetwork(requestNetwork);
    }
    setIsLoading(false);
  };

  const sanitizePath = (path: string) => {
    const regex = /^\/sign\/(eth|cosmos)\/(.+)\/(.+)$/;
    const match = path.match(regex);

    if (match) {
      const [network, address, message] = match;
      return {
        network,
        address,
        message,
      };
    } else {
      navigation.navigate('InvalidPath');
    }
    return null;
  };

  useEffect(() => {
    if (route.path) {
      const sanitizedRoute = sanitizePath(route.path);
      sanitizedRoute &&
        route.params &&
        retrieveData(
          route.params?.network,
          route.params?.address,
          route.params?.message,
        );
      return;
    }
    route.params &&
      retrieveData(
        route.params?.network,
        route.params?.address,
        route.params?.message,
      );
  }, [route]);

  const handleWalletConnectRequest = async () => {
    const { requestEvent } = route.params || {};

    if (!account) {
      throw new Error('account not found');
    }

    const response = await approveWalletConnectRequest(
      requestEvent,
      account,
      network,
      message,
    );

    const { topic } = requestEvent;
    await web3wallet.respondSessionRequest({ topic, response });
  };

  const handleIntent = async () => {
    if (!account) {
      throw new Error('Account is not valid');
    }
    if (message) {
      const signedMessage = await signMessage({
        message,
        network,
        accountId: account.counterId,
      });
      Alert.alert('Signature', signedMessage);
    }
  };

  const signMessageHandler = async () => {
    if (route.params?.requestEvent) {
      await handleWalletConnectRequest();
    } else {
      await handleIntent();
    }

    navigation.navigate('Laconic');
  };

  const rejectRequestHandler = async () => {
    if (route.params?.requestEvent) {
      const response = rejectEIP155Request(route.params?.requestEvent);
      const { topic } = route.params?.requestEvent;
      await web3wallet.respondSessionRequest({
        topic,
        response,
      });
    }
    navigation.navigate('Laconic');
  };

  return (
    <>
      {isLoading ? (
        <View style={styles.spinnerContainer}>
          <ActivityIndicator size="large" color="#0000ff" />
        </View>
      ) : (
        <View style={styles.appContainer}>
          <View style={styles.dappDetails}>
            {requestIcon && (
              <Image
                style={styles.dappLogo}
                source={requestIcon ? { uri: requestIcon } : undefined}
              />
            )}
            <Text>{requestName}</Text>
            <Text variant="bodyMedium">{requestURL}</Text>
          </View>
          <AccountDetails account={account} />
          <View style={styles.requestMessage}>
            <Text variant="bodyLarge">{message}</Text>
          </View>
          <View style={styles.buttonContainer}>
            <Button mode="contained" onPress={signMessageHandler}>
              Yes
            </Button>
            <Button
              mode="contained"
              onPress={rejectRequestHandler}
              buttonColor="#B82B0D">
              No
            </Button>
          </View>
        </View>
      )}
    </>
  );
};

export default SignRequest;
