import React, {
  memo,
  useCallback,
  useEffect,
  useMemo,
  useRef,
  useState,
} from 'react';
import {ViewStyle} from 'react-native';
import {KeyboardAvoidingView} from 'react-native-keyboard-controller';
import {useSafeAreaInsets} from 'react-native-safe-area-context';
import Animated, {
  runOnJS,
  useAnimatedStyle,
  useSharedValue,
  withTiming,
} from 'react-native-reanimated';
import {
  WebView,
  WebViewRef,
  WebViewMessageEvent,
  WebViewNavigation,
  WebViewOpenWindowEvent,
} from '@components/_core/WebView';
import {AiChatbotUserConfig} from '@interfaces/instance';
import {useInstance, useUser} from '@redux/selectors';
import {getInstanceChatbot} from '@services/instance';
import {openUrlFromApp, wait} from '@shared/utils';
import {HUMAND_URL} from '@shared/keys';

import BotButton from './components/BotButton';
import CloseButton from './components/CloseButton';
import {
  ANIMATION_DURATION,
  CHATBOT_NAME,
  getChatBotHtml,
  KEYBOARD_OFFSET,
} from './constants';
import {styles} from './styles';

export {CHATBOT_NAME};

function VoiceFlowWebChatComponent({isFullscreen = false}) {
  const currentUser = useUser();
  const webViewRef = useRef<Nullable<WebViewRef>>(null);
  const instance = useInstance();
  const {top: marginTop} = useSafeAreaInsets();
  const opacity = useSharedValue(0);
  const [aiChatbotConfig, setAiChatbotConfig] =
    useState<Nullable<AiChatbotUserConfig>>(null);
  const [isBotEnabled, setIsBotEnabled] = useState(false);
  const [isBotLoading, setIsBotLoading] = useState(true);

  const animatedStyle = useAnimatedStyle(() => {
    if (!_WORKLET) {
      return {opacity: isFullscreen ? 1 : 0};
    }
    return {
      opacity: isFullscreen ? 1 : opacity.value,
    };
  });

  const source = useMemo(
    () => ({
      html: getChatBotHtml({
        aiChatbotConfig,
        user: currentUser,
        instance,
        isFullscreen,
      }),
      baseUrl: HUMAND_URL,
    }),
    [aiChatbotConfig, currentUser, instance, isFullscreen],
  );

  useEffect(() => {
    const initChatBot = async () => {
      try {
        const chatbotConfig = await getInstanceChatbot();
        setAiChatbotConfig(chatbotConfig);
      } catch (error) {
        // No chatbot instance available
      }
    };
    initChatBot();
  }, []);

  const onMessage = (event: WebViewMessageEvent) => {
    if (event.nativeEvent.data === 'READY') {
      setIsBotLoading(false);
    }
  };

  const onActivateBot = () => {
    setIsBotEnabled(true);
    opacity.value = withTiming(1, {duration: ANIMATION_DURATION});
  };

  const onDisableBot = useCallback(() => {
    if (isFullscreen) {
      return;
    }
    opacity.value = withTiming(0, {duration: ANIMATION_DURATION}, finished => {
      finished && runOnJS(setIsBotEnabled)(false);
    });
  }, [isFullscreen, opacity]);

  const onPressChatBotLink = async (url: string) => {
    if (url !== 'about:blank' && url !== HUMAND_URL) {
      webViewRef.current?.stopLoading();
      onDisableBot();
      // To prevent overlapping animations between the WebView modal and the InAppBrowser
      await wait(250);
      openUrlFromApp(url, true);
    }
  };

  const onNavigationStateChange = (event: WebViewNavigation) => {
    onPressChatBotLink(event.url);
  };

  const onOpenWindow = (event: WebViewOpenWindowEvent) => {
    onPressChatBotLink(event.nativeEvent.targetUrl);
  };

  const memoizedStyles = useMemo(() => {
    return [styles.container, {marginTop}, animatedStyle];
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [marginTop]);

  return aiChatbotConfig?.aiChatbotId ? (
    <>
      <Animated.View
        pointerEvents={isBotEnabled || isFullscreen ? 'box-none' : 'none'}
        style={memoizedStyles}>
        <KeyboardAvoidingView
          behavior="height"
          keyboardVerticalOffset={KEYBOARD_OFFSET}
          style={styles.keyboardContainer}>
          <WebView
            javaScriptEnabled
            onMessage={onMessage}
            onNavigationStateChange={onNavigationStateChange}
            onOpenWindow={onOpenWindow}
            ref={webViewRef}
            source={source}
            scrollEnabled={false}
            style={styles.webView}
          />
        </KeyboardAvoidingView>
      </Animated.View>
      {!isFullscreen && (
        <>
          {isBotEnabled && (
            <CloseButton
              onClose={onDisableBot}
              style={animatedStyle as ViewStyle}
            />
          )}
          <BotButton
            show={!isBotEnabled && !isBotLoading}
            onPress={onActivateBot}
          />
        </>
      )}
    </>
  ) : null;
}

export const VoiceFlowWebChat = memo(VoiceFlowWebChatComponent);

export function ChatbotScreen() {
  return <VoiceFlowWebChat isFullscreen />;
}
