import React from 'react'
import { View, Animated, Easing } from 'react-native'
import Svg, { Circle } from 'react-native-svg'
import {
  DURATION,
  SVG_CIRCUMFERENCE,
  SVG_SIZE,
  SVG_CENTER,
  SPINNER_RADIUS,
  SPINNER_DASHARRAY_HALF,
  SPINNER_DASHARRAY_MIN,
  SPINNER_DASHOFFSET_FACTOR,
  propTypes
} from './shared'
import { useA11yInfo } from '../A11yInfoProvider/A11yInfoProvider'

export const Spinner = React.forwardRef(
  ({ size, color, indicatorBackgroundColor, thickness, label, isStatic = false }, ref) => {
    const { reduceMotionEnabled } = useA11yInfo()
    const reduceMotion = reduceMotionEnabled || isStatic

    // Animated value between 0..1 that will loop
    const progress = React.useRef(new Animated.Value(0)).current

    // Local state to force re-render on each frame
    const [progressVal, setProgressVal] = React.useState(0)

    React.useEffect(() => {
      if (reduceMotion) {
        progress.stopAnimation(() => {
          progress.setValue(0)
          setProgressVal(0)
        })
        return undefined
      }

      const id = progress.addListener(({ value }) => {
        setProgressVal(value)
      })

      Animated.loop(
        Animated.timing(progress, {
          toValue: 1,
          duration: DURATION,
          easing: Easing.linear,
          useNativeDriver: false,
          isInteraction: false
        })
      ).start()

      return () => {
        progress.removeListener(id)
        progress.stopAnimation()
      }
    }, [progress, reduceMotion])

    /* The same logic used in Wweb keyframes:
    - rotation from -90° base plus 0..183° => -90..93
    - dasharray from 1% -> 50% -> 1%
    - dashoffset from 0 -> 0 -> -49%
  */

    // 1) rotation (0->183) plus base offset -90
    const rotationDeg = -90 + 183 * progressVal // -90..+93

    // strokeDasharray
    let dashArrayVisible
    if (progressVal < SPINNER_DASHARRAY_HALF) {
      const segmentProgress = progressVal / SPINNER_DASHARRAY_HALF
      dashArrayVisible =
        SPINNER_DASHARRAY_MIN + (SPINNER_DASHARRAY_HALF - SPINNER_DASHARRAY_MIN) * segmentProgress
    } else {
      const segmentProgress = (progressVal - SPINNER_DASHARRAY_HALF) / SPINNER_DASHARRAY_HALF
      dashArrayVisible =
        SPINNER_DASHARRAY_HALF + (SPINNER_DASHARRAY_MIN - SPINNER_DASHARRAY_HALF) * segmentProgress
    }

    const visibleLength = dashArrayVisible * SVG_CIRCUMFERENCE
    const invisibleLength = SVG_CIRCUMFERENCE - visibleLength
    const strokeDasharray = `${visibleLength},${invisibleLength}`

    // strokeDashoffset
    let strokeDashoffset = 0
    if (progressVal > SPINNER_DASHARRAY_HALF) {
      const segmentProgress = (progressVal - SPINNER_DASHARRAY_HALF) / SPINNER_DASHARRAY_HALF
      strokeDashoffset = -SPINNER_DASHOFFSET_FACTOR * SVG_CIRCUMFERENCE * segmentProgress
    }

    const strokeWidth = (thickness * SVG_SIZE) / size

    return (
      <View
        ref={ref}
        style={{ width: size, height: size }}
        accessible
        accessibilityLabel={label}
        accessibilityRole="progressbar"
        accessibilityState={{ busy: true }}
      >
        <Svg width={size} height={size} viewBox={`0 0 ${SVG_SIZE} ${SVG_SIZE}`}>
          {/* Base static circle */}
          <Circle
            cx={SVG_CENTER}
            cy={SVG_CENTER}
            r={SPINNER_RADIUS}
            fill="none"
            stroke={indicatorBackgroundColor}
            strokeWidth={strokeWidth}
          />

          {/* Animated circle */}
          <Circle
            cx={SVG_CENTER}
            cy={SVG_CENTER}
            r={SPINNER_RADIUS}
            fill="none"
            stroke={color}
            strokeWidth={strokeWidth}
            strokeLinecap="round"
            transform={`rotate(${rotationDeg}, 24, 24)`}
            strokeDasharray={strokeDasharray}
            strokeDashoffset={strokeDashoffset}
          />
        </Svg>
      </View>
    )
  }
)

Spinner.displayName = 'Spinner'
Spinner.propTypes = propTypes
