import React, {ReactNode, useEffect} from 'react';
import {StyleProp, View, ViewStyle} from 'react-native';
import Animated, {
  Easing,
  useAnimatedStyle,
  useSharedValue,
  withDelay,
  withRepeat,
  withTiming,
} from 'react-native-reanimated';
import {Typography} from '@components/_core/Typography';
import {Title} from '@components/_HuGo/Title';
import {windowDimensions} from '@shared/constants';
import {useTheme} from '@shared/theme';
import {getPercentage} from '@shared/utils';

import {styles} from './styles';

export interface ProgressBarProps {
  /**
   * A value between 0 and the `total` prop. If `progress` is more than `total`, the final progress will always be 100%
   */
  progress?: number;
  /**
   * Default: 100
   */
  total?: number;
  title?: string;
  description?: string;
  helper?: string | ReactNode;
  rightSideText?: string;
  showPercentage?: boolean;
  fractionDigits?: number;
  /**
   * Use this prop to show a "loader" animation. When this value is defined, `progress` and `total` are ignored
   */
  indeterminate?: boolean;
  style?: StyleProp<ViewStyle>;
  color?: string;
  withAnimation?: boolean;
}

export function ProgressBar({
  description,
  helper,
  showPercentage,
  title,
  style,
  fractionDigits,
  indeterminate,
  rightSideText,
  progress = 0,
  total = 100,
  color,
  withAnimation = true,
}: ProgressBarProps) {
  const {theme} = useTheme();
  const animatedProgress = useSharedValue(
    indeterminate ? -windowDimensions.width : 0,
  );
  // To avoid values more than 100%
  const safeProgress = Math.min(progress, total);
  const percentage = getPercentage({
    current: safeProgress,
    total,
    decimals: fractionDigits,
  });

  useEffect(() => {
    if (indeterminate) {
      animatedProgress.value = withRepeat(
        withDelay(
          500,
          withTiming(windowDimensions.width, {
            duration: 1000,
            easing: Easing.linear,
          }),
        ),
        -1,
        false,
      );
    } else {
      // TODO: Check with Angel
      animatedProgress.value = withAnimation
        ? withTiming(parseFloat(percentage), {
            duration: 250,
          })
        : parseFloat(percentage);
    }
  }, [animatedProgress, percentage, indeterminate, withAnimation]);

  const animatedStyle = useAnimatedStyle(() => {
    const translateX = animatedProgress.value;
    return indeterminate
      ? {width: '40%', transform: [{translateX}]}
      : {width: `${animatedProgress.value}%`};
  });

  return (
    <View style={[styles.container, style]}>
      {!!title && <Title title={title} description={description} size="s" />}
      <View
        style={[
          styles.middleContainer,
          (!!rightSideText || !!showPercentage) && styles.middleGap,
        ]}>
        <View style={styles.progressContainer}>
          <View
            style={[
              styles.line,
              {backgroundColor: theme.border.neutral.default},
            ]}
          />
          <Animated.View
            style={[
              styles.progressLine,
              {backgroundColor: color || theme.graphics.hugo[500]},
              animatedStyle,
            ]}
          />
        </View>
        <View>
          {rightSideText ? (
            <Typography variant="xs" color={theme.text.neutral.lighter}>
              {rightSideText}
            </Typography>
          ) : showPercentage ? (
            <Typography variant="xs" color={theme.text.neutral.lighter}>
              {percentage}%
            </Typography>
          ) : null}
        </View>
      </View>
      {!!helper && (
        <Typography variant="xxs" color={theme.text.neutral.lighter}>
          {helper}
        </Typography>
      )}
    </View>
  );
}
