import { StatusBar } from 'expo-status-bar';
import { useEffect, useMemo, useRef, useState } from 'react';
import { BackHandler, Linking, Platform, StyleSheet, View } from 'react-native';
import type { WebViewMessageEvent } from 'react-native-webview';
import { WebView } from 'react-native-webview';

import {
  handleMobileHostBridgeMessage,
  MOBILE_HOST_CAPABILITIES,
} from './src/mobileHostBridge';
import { shouldOpenInMobileShellWebView } from './src/mobileShellNavigation';
import { buildMobileShellUrl } from './src/mobileShellUrl';

const defaultWebUrl = 'http://127.0.0.1:3000/';

export default function App() {
  const webViewRef = useRef<WebView>(null);
  const [canGoBack, setCanGoBack] = useState(false);
  const webUrl = useMemo(
    () =>
      buildMobileShellUrl(
        process.env.EXPO_PUBLIC_GENARRATIVE_WEB_URL || defaultWebUrl,
        {
          platform: Platform.OS === 'ios' ? 'ios' : 'android',
          hostVersion: '0.1.0',
          capabilities: MOBILE_HOST_CAPABILITIES,
        },
      ),
    [],
  );
  const allowedWebOrigin = useMemo(() => new URL(webUrl).origin, [webUrl]);

  useEffect(() => {
    const subscription = BackHandler.addEventListener(
      'hardwareBackPress',
      () => {
        if (!canGoBack) {
          return false;
        }

        webViewRef.current?.goBack();
        return true;
      },
    );

    return () => subscription.remove();
  }, [canGoBack]);

  const handleMessage = (event: WebViewMessageEvent) => {
    void handleMobileHostBridgeMessage(event.nativeEvent.data, (response) => {
      webViewRef.current?.injectJavaScript(
        `window.dispatchEvent(new MessageEvent('message', { data: ${JSON.stringify(
          JSON.stringify(response),
        )} })); true;`,
      );
    });
  };

  const handleShouldStartLoad = (request: { url: string }) => {
    if (shouldOpenInMobileShellWebView(request.url, allowedWebOrigin)) {
      return true;
    }

    void Linking.openURL(request.url).catch(() => undefined);
    return false;
  };

  return (
    <View style={styles.root}>
      <StatusBar style="auto" />
      <WebView
        ref={webViewRef}
        source={{ uri: webUrl }}
        javaScriptEnabled
        domStorageEnabled
        originWhitelist={[allowedWebOrigin]}
        onMessage={handleMessage}
        onShouldStartLoadWithRequest={handleShouldStartLoad}
        onNavigationStateChange={(event) => setCanGoBack(event.canGoBack)}
        setSupportMultipleWindows={false}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  root: {
    flex: 1,
    backgroundColor: '#fffdf9',
  },
});
