import React, { Fragment, useRef, useState } from 'react';
import {
  StyleSheet,
  View,
  Platform,
  ActivityIndicator,
  Text,
  Linking,
} from 'react-native';
import { WebView, type WebViewMessageEvent } from 'react-native-webview';
import { clientSdkBaseUrl, serverSdkBaseUrl } from '../lib/config';
import { getContact } from '../functions';
import { Registration } from './views/Registration';
import { BvnVerification } from './views/BvnVerification';
import { PaylaterAgreement } from './views/PaylaterAgreement';
import { PaymentLinking } from './views/PaymentLinking';
import { FaceVerification } from './views/FaceVerification';

type OmnipayProps = {
  color: string;
  env: 'dev' | 'prod';
  publicKey: string;
  phoneNumber: string;
  view: 'bills' | 'registration';
  onEnterFullScreen?: () => void;
  onExitFullScreen?: () => void;
};

type PostMessage = {
  [key: string]: unknown;
};

type Status = 'error' | 'loading' | 'success';

const Omnipay = ({
  color,
  env,
  publicKey,
  phoneNumber,
  view,
  onEnterFullScreen,
  onExitFullScreen,
}: OmnipayProps): JSX.Element => {
  const webviewRef = useRef<WebView>(null);
  const [webviewStatus, setWebviewStatus] = useState<Status>('loading');
  const webHost = getWebHost();
  const webUrl = getWebUrl();

  const onWebviewMount = `
      window.nativeOs = ${Platform.OS};
      true;
    `;

  function getWebHost() {
    /**
     * use client rendered app url for bills sdk,
     * else use server rendered app url
     */
    if (view === 'bills') {
      return clientSdkBaseUrl[env];
    }
    return serverSdkBaseUrl[env];
  }

  function getWebUrl() {
    const themeColor = color.includes('#') ? color.split('#')[1] : color;
    if (view === 'bills') {
      return `${webHost}?theme=${themeColor}&view=${view}&publicKey=${publicKey}&phoneNumber=${phoneNumber}`;
    }
    return `${webHost}auth/register?theme=${themeColor}&publicKey=${publicKey}&phoneNumber=${phoneNumber}`;
  }

  function postMessage(data: PostMessage) {
    if (!webviewRef.current) {
      return;
    }
    try {
      webviewRef.current.postMessage(JSON.stringify(data));
    } catch (error) {}
  }

  async function onWebviewMessage(e: WebViewMessageEvent) {
    try {
      if (e.nativeEvent && e.nativeEvent.data) {
        const eventData = JSON.parse(e.nativeEvent.data);
        const { dataKey, dataValue } = eventData;
        if (dataKey === 'chooseContact') {
          const contactDetails = await getContact();
          postMessage({
            dataKey: 'contactSelected',
            dataValue: contactDetails,
          });
        }
        if (dataKey === 'modalOpen') {
          if (onEnterFullScreen) {
            onEnterFullScreen();
          }
        }
        if (dataKey === 'modalClosed') {
          if (onExitFullScreen) {
            onExitFullScreen();
          }
        }
        if (dataKey === 'openLink') {
          Linking.openURL(dataValue);
        }
      }
    } catch (error) {}
  }

  if (view !== 'bills' && view !== 'registration') {
    return <Text>Invalid view</Text>;
  }

  if (!publicKey.includes('OMNIPUBKEY_')) {
    return <Text>Invalid public key</Text>;
  }

  if (phoneNumber.length < 10) {
    return <Text>Invalid phone number</Text>;
  }

  if (color.length < 3) {
    return <Text>Invalid color</Text>;
  }

  if (!['dev', 'prod'].includes(env)) {
    return <Text>Invalid environment</Text>;
  }

  return (
    <Fragment>
      <View style={styles.full}>
        <WebView
          source={{
            uri: webUrl,
          }}
          style={styles.webview}
          injectedJavaScriptBeforeContentLoaded={onWebviewMount}
          onMessage={onWebviewMessage}
          ref={webviewRef}
          onLoadEnd={() => setWebviewStatus('success')}
        />
        {webviewStatus === 'loading' && (
          <View style={styles.webviewLoader}>
            <ActivityIndicator size="small" color={color} />
          </View>
        )}
      </View>
    </Fragment>
  );
};

const styles = StyleSheet.create({
  hide: {
    display: 'none',
  },
  full: {
    flex: 1,
    width: '100%',
    height: '100%',
  },
  webview: {
    flex: 1,
    width: '100%',
    height: '100%',
  },
  webviewLoader: {
    zIndex: 3,
    backgroundColor: 'white',
    alignItems: 'center',
    justifyContent: 'center',
    flex: 1,
    width: '100%',
    height: '100%',
    position: 'absolute',
    top: 0,
    left: 0,
  },
});

Omnipay.Registration = Registration;
Omnipay.BvnVerification = BvnVerification;
Omnipay.PaylaterAgreement = PaylaterAgreement;
Omnipay.PaymentLinking = PaymentLinking;
Omnipay.FaceVerification = FaceVerification;
export default Omnipay;
