import { useTheme } from '@emotion/react';
import type { ReactElement } from 'react';
import React, { useEffect, useRef } from 'react';
import { Animated, Easing, View } from 'react-native';
import Svg, { Circle, G } from 'react-native-svg';
import type { ViewProps, StyleProp, ViewStyle } from 'react-native';
import { StyledContainer, StyledDonutCircle } from './StyledProgressCircle';
import Typography from '../Typography';
import { THEME_INTENT_MAP } from './constants';
import { hexToRgba } from '../../utils/helpers';

export interface ProgressCircleProps extends ViewProps {
  /**
   * The progress completion percentage: 0-100.
   */
  value: number;
  /*
   * Custom displayed value.
   */
  renderValue?: (value: number) => React.ReactNode;
  /**
   * Set intent for your progress.
   */
  intent?:
    | 'primary'
    | 'success'
    | 'warning'
    | 'danger'
    | 'info'
    | 'archived'
    | 'primary-inverted'
    | 'success-inverted'
    | 'warning-inverted'
    | 'danger-inverted'
    | 'info-inverted'
    | 'archived-inverted';
  /**
   * Additional style.
   */
  style?: StyleProp<ViewStyle>;
  /*
   * Testing id of the component.
   */
  testID?: string;
}

const defaultRenderValue = (value: number) => `${value}%`;
const AnimatedCircle = Animated.createAnimatedComponent(Circle);

const ProgressCircle = ({
  value,
  renderValue = defaultRenderValue,
  intent = 'primary',
  style,
  testID,
  ...nativeProps
}: ProgressCircleProps): ReactElement => {
  const theme = useTheme();
  const size = theme.__hd__.progress.sizes.circleDiameter;
  const strokeWidth = theme.__hd__.progress.sizes.circleCompletenessHeight;
  const radius = size / 2 - strokeWidth;
  const circumference = 2 * Math.PI * radius;

  const progressAnimatedValue = useRef(new Animated.Value(0)).current;
  const minArc = strokeWidth / 2 / Math.PI; // Minimum arc length

  useEffect(() => {
    Animated.timing(progressAnimatedValue, {
      toValue: value,
      useNativeDriver: true,
      easing: Easing.inOut(Easing.ease),
    }).start();
  }, [value]);

  const strokeDashoffset = progressAnimatedValue.interpolate({
    inputRange: [0, 100],
    outputRange: [circumference - minArc, 0], // Full circle to zero offset
  });

  return (
    <View {...nativeProps} testID={testID} style={style}>
      <StyledContainer>
        <Svg width={size} height={size} viewBox={`0 0 ${size} ${size}`}>
          {/* rotation -90 in order to move start point from 3 o'clock to 12 o'clock */}
          <G rotation="-90" origin={`${size / 2}, ${size / 2}`}>
            {/* Background Circle */}
            <Circle
              cx={size / 2}
              cy={size / 2}
              r={radius}
              stroke={hexToRgba(
                theme.__hd__.progress.colors.incompleteness[
                  THEME_INTENT_MAP[intent]
                ],
                0.1
              )}
              strokeWidth={strokeWidth}
              fill="transparent"
            />
            {/* Progress Circle */}
            <AnimatedCircle
              cx={size / 2}
              cy={size / 2}
              r={radius}
              stroke={
                theme.__hd__.progress.colors.completeness[
                  THEME_INTENT_MAP[intent]
                ]
              }
              strokeWidth={strokeWidth}
              fill="transparent"
              strokeDasharray={circumference}
              strokeDashoffset={strokeDashoffset}
              strokeLinecap="round"
            />
          </G>
        </Svg>
        <StyledDonutCircle>
          <Typography.Body>{renderValue(value)}</Typography.Body>
        </StyledDonutCircle>
      </StyledContainer>
    </View>
  );
};

export default ProgressCircle;
