import React, {
  memo,
  useCallback,
  useEffect,
  useMemo,
  useRef,
  useState,
} from 'react';
import {StyleSheet, View} from 'react-native';
import {useTranslation} from 'react-i18next';
import Animated, {
  FadeInUp,
  FadeOutDown,
  LinearTransition,
} from 'react-native-reanimated';
import {Typography} from '@components/index';
import {useAiSummary} from '@modules/chats/contexts';
import {AiSummaryStatus} from '@modules/chats/interfaces';
import {CHATS_SPACING} from '@modules/chats/utils';
import {SPACING, useTheme} from '@shared/theme';

import {Spinner} from './Spinner';

const VISIBLE_STATUSES: AiSummaryStatus[] = [
  'compressing',
  'uploading',
  'summarizing',
];

const ANIMATION_DURATION = 300;
const MIN_DISPLAY_MS = 1000;
const REDACTING_DELAY_MS = 4500;

export const AiSummaryProcessingText = memo(() => {
  const {t} = useTranslation();
  const {theme} = useTheme();
  const {state} = useAiSummary();
  const [displayText, setDisplayText] = useState<Nullable<string>>(null);
  const isVisible = VISIBLE_STATUSES.includes(state.status);
  const labels = useMemo(
    () =>
      ({
        compressing: t('chat.voicenote_ceo.processing'),
        uploading: t('chat.voicenote_ceo.processing'),
        summarizing: t('chat.voicenote_ceo.summarizing'),
        drafting: t('chat.voicenote_ceo.drafting'),
      } as Record<AiSummaryStatus | 'drafting', string>),
    [t],
  );

  const queueRef = useRef<string[]>([]);
  const currentTextRef = useRef<string | null>(null);
  const displayedAtRef = useRef<number>(0);
  const drainTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
  const redactingTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
  const lockedRef = useRef(false);

  const show = useCallback((text: string) => {
    currentTextRef.current = text;
    displayedAtRef.current = Date.now();
    if (text === labels.drafting) {
      lockedRef.current = true;
    }
    setDisplayText(text);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  const drainQueue = useCallback(() => {
    drainTimerRef.current = null;
    if (lockedRef.current || queueRef.current.length === 0) {
      return;
    }

    const elapsed = Date.now() - displayedAtRef.current;
    const remaining = MIN_DISPLAY_MS - elapsed;

    if (remaining > 0) {
      drainTimerRef.current = setTimeout(drainQueue, remaining);
      return;
    }

    const next = queueRef.current.shift()!;
    show(next);

    if (!lockedRef.current && queueRef.current.length > 0) {
      drainTimerRef.current = setTimeout(drainQueue, MIN_DISPLAY_MS);
    }
  }, [show]);

  const enqueue = useCallback(
    (text: string) => {
      if (lockedRef.current) {
        return;
      }

      if (!currentTextRef.current && queueRef.current.length === 0) {
        show(text);
        return;
      }

      const lastQueued = queueRef.current[queueRef.current.length - 1];
      if (
        lastQueued === text ||
        (queueRef.current.length === 0 && currentTextRef.current === text)
      ) {
        return;
      }

      queueRef.current.push(text);
      if (!drainTimerRef.current) {
        drainQueue();
      }
    },
    [show, drainQueue],
  );

  useEffect(() => {
    const text = labels[state.status];
    if (text) {
      enqueue(text);
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [state.status, enqueue]);

  useEffect(() => {
    if (state.status === 'summarizing') {
      redactingTimerRef.current = setTimeout(() => {
        enqueue(labels.drafting);
      }, REDACTING_DELAY_MS);
    }

    return () => {
      if (redactingTimerRef.current) {
        clearTimeout(redactingTimerRef.current);
        redactingTimerRef.current = null;
      }
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [state.status, enqueue]);

  useEffect(() => {
    if (!isVisible) {
      queueRef.current = [];
      currentTextRef.current = null;
      displayedAtRef.current = 0;
      lockedRef.current = false;
      if (drainTimerRef.current) {
        clearTimeout(drainTimerRef.current);
        drainTimerRef.current = null;
      }
      if (redactingTimerRef.current) {
        clearTimeout(redactingTimerRef.current);
        redactingTimerRef.current = null;
      }
      setDisplayText(null);
    }
  }, [isVisible]);

  if (!isVisible || !displayText) {
    return null;
  }

  return (
    <View style={styles.container}>
      <Spinner />
      <Animated.View
        key={displayText}
        entering={FadeInUp.duration(ANIMATION_DURATION)}
        exiting={FadeOutDown.duration(ANIMATION_DURATION)}
        layout={LinearTransition.duration(ANIMATION_DURATION)}>
        <Typography
          variant="xs"
          color={theme.text.neutral.lighter}
          numberOfLines={1}>
          {displayText}
        </Typography>
      </Animated.View>
    </View>
  );
});

const styles = StyleSheet.create({
  container: {
    alignItems: 'center',
    flexDirection: 'row',
    gap: SPACING.x1,
    paddingHorizontal: SPACING.x2,
    paddingVertical: SPACING['x0.5'],
    position: 'absolute',
    bottom: 0,
    left: 0,
    right: 0,
    height: CHATS_SPACING.inputMinHeight,
    overflow: 'hidden',
  },
});
