import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react';
import {View} from 'react-native';
import {useTranslation} from 'react-i18next';
import RNWebView from 'react-native-webview';
import {useNavigation} from '@react-navigation/native';
import {BackButton, WebView, WebViewMessageEvent} from '@components';
import {Language} from '@config/i18n';
import {tokenManager} from '@config/tokens';
import {useBackHandler} from '@hooks/useBackHandler';
import {Navigation} from '@interfaces/navigation';
import {showSnackbar} from '@redux/dispatchers';
import {Screens} from '@shared/constants';
import {HUMAND_URL} from '@shared/keys';
import {useTheme} from '@shared/theme';

import {useProdeAccess} from '../../hooks/useProdeAccess';
import {SportsPoolSplash} from '../../components/SportsPoolSplash';
import {styles} from './styles';

const READY_GRACE_PERIOD_MS = 2400;
const READY_FALLBACK_MS = 10000;

function ProdeWebView({route: {params}}: Navigation<Screens.PRODE_WEBVIEW>) {
  const {theme} = useTheme();
  const navigation = useNavigation();
  const refreshToken = tokenManager.getRefreshToken();
  const [webCanGoBack, setWebCanGoBack] = useState(false);
  const [isReady, setIsReady] = useState(false);
  const hasReached = useRef(false);
  const webViewRef = useRef<RNWebView>(null);
  const {t, i18n} = useTranslation();
  const competitionId = params?.competitionId;

  const {data: accessData} = useProdeAccess();

  const source = useMemo(() => {
    const basePath = competitionId
      ? `sports-pool-mobile/${refreshToken}/${competitionId}`
      : `sports-pool-mobile/${refreshToken}`;
    return {uri: `${HUMAND_URL}${basePath}`};
  }, [refreshToken, competitionId]);

  const onMessage = useCallback((event: WebViewMessageEvent) => {
    const data = event.nativeEvent.data;

    if (!hasReached.current && data === 'READY') {
      hasReached.current = true;
      // Grace period for the SPA's initial data fetch, which starts after mount
      setTimeout(() => setIsReady(true), READY_GRACE_PERIOD_MS);
      return;
    }

    try {
      const parsed = JSON.parse(data);
      if (parsed.type === 'ROUTE_CHANGE') {
        setWebCanGoBack(Boolean(parsed.canGoBack));
      }
    } catch {
      // No need to handle errors, but is required to catch them to avoid component crashed
    }
  }, []);

  useEffect(() => {
    // Fallback in case READY never arrives (network error, web bug)
    const timer = setTimeout(() => setIsReady(true), READY_FALLBACK_MS);
    return () => clearTimeout(timer);
  }, []);

  const onError = useCallback(() => {
    showSnackbar({title: t('errors.api.404')});
  }, [t]);

  const handleBack = useCallback(() => {
    if (!competitionId && webCanGoBack) {
      webViewRef.current?.goBack();
    } else {
      navigation.goBack();
    }
    return true;
  }, [competitionId, navigation, webCanGoBack]);

  useEffect(() => {
    const headerLeft = () => <BackButton onPress={handleBack} />;
    const title =
      accessData?.moduleNameTranslations?.[i18n.language as Language] ||
      accessData?.moduleName ||
      t('sportsPool.title');
    navigation.setOptions({
      gestureEnabled: !webCanGoBack || !!competitionId,
      headerLeft,
      title,
    });
  }, [
    navigation,
    handleBack,
    webCanGoBack,
    competitionId,
    accessData,
    i18n.language,
    t,
  ]);

  useBackHandler(handleBack);

  return (
    <View
      style={[
        styles.container,
        {backgroundColor: theme.background.layout.default},
      ]}>
      <WebView
        ref={webViewRef}
        bounces={false}
        source={source}
        onError={onError}
        onMessage={onMessage}
        mixedContentMode="always"
        scalesPageToFit={false}
        overScrollMode="never"
        showsVerticalScrollIndicator={true}
        showsHorizontalScrollIndicator={false}
        allowsBackForwardNavigationGestures={false}
        setSupportMultipleWindows={false}
        allowsLinkPreview={false}
        mediaPlaybackRequiresUserAction={true}
        style={[styles.webview, !isReady && styles.hidden]}
      />
      {!isReady && (
        <View style={styles.splash}>
          <SportsPoolSplash />
        </View>
      )}
    </View>
  );
}

export default ProdeWebView;
