import React, { useEffect, memo } from 'react';
import { StyleSheet, View } from 'react-native';
import { Svg, Path } from 'react-native-svg';
import Animated, {
    Easing,
    interpolate,
    useAnimatedStyle,
    useSharedValue,
    withDelay,
    withRepeat,
    withTiming
} from 'react-native-reanimated';

import { useTheme } from '../../branding';
import {
    STAR_OPACITY_RANGE,
    STAR_SCALE_RANGE,
    STAR_TRANSLATE_Y_RANGE,
    STAR_TRANSLATE_X_RANGE,
    STAR_FLOAT_DELAY_MULTIPLIER,
    STAR_FLOAT_DURATION_MULTIPLIER
} from './constants';

interface StarProps {
    size: number;
    top: number | `${number}%`;
    left: number | `${number}%`;
    delay: number;
    duration: number;
    color: string;
}

const Star = memo<StarProps>(({ size, top, left, delay, duration, color }) => {
    const twinkle = useSharedValue(0);
    const float = useSharedValue(0);

    useEffect(() => {
        twinkle.value = withDelay(
            delay,
            withRepeat(
                withTiming(1, {
                    duration,
                    easing: Easing.inOut(Easing.quad)
                }),
                -1,
                true
            )
        );

        float.value = withDelay(
            delay * STAR_FLOAT_DELAY_MULTIPLIER,
            withRepeat(
                withTiming(1, {
                    duration: duration * STAR_FLOAT_DURATION_MULTIPLIER,
                    easing: Easing.inOut(Easing.sin)
                }),
                -1,
                true
            )
        );
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, []);

    const animatedStyle = useAnimatedStyle(() => {
        const opacity = interpolate(
            twinkle.value,
            [0, 1],
            [STAR_OPACITY_RANGE.min, STAR_OPACITY_RANGE.max]
        );
        const scale = interpolate(
            twinkle.value,
            [0, 1],
            [STAR_SCALE_RANGE.min, STAR_SCALE_RANGE.max]
        );
        const translateY = interpolate(
            float.value,
            [0, 1],
            [STAR_TRANSLATE_Y_RANGE.min, STAR_TRANSLATE_Y_RANGE.max]
        );
        const translateX = interpolate(
            float.value,
            [0, 1],
            [STAR_TRANSLATE_X_RANGE.min, STAR_TRANSLATE_X_RANGE.max]
        );

        return {
            opacity,
            transform: [{ scale }, { translateY }, { translateX }]
        };
    });

    return (
        <Animated.View style={[styles.star, { top, left }, animatedStyle]}>
            <Svg height={size} width={size} viewBox="0 0 27 27">
                <Path
                    d="M12.598 0.295242C12.8411 -0.0983972 13.4136 -0.0983965 13.6567 0.295243L18.277 7.77509C18.3278 7.85735 18.3971 7.92665 18.4794 7.97746L25.9592 12.5977C26.3529 12.8409 26.3529 13.4133 25.9592 13.6565L18.4794 18.2768C18.3971 18.3276 18.3278 18.3969 18.277 18.4792L13.6567 25.959C13.4136 26.3526 12.8411 26.3526 12.598 25.959L7.97771 18.4792C7.92689 18.3969 7.8576 18.3276 7.77533 18.2768L0.295486 13.6565C-0.0981531 13.4133 -0.0981523 12.8409 0.295487 12.5977L7.77533 7.97746C7.8576 7.92665 7.92689 7.85735 7.97771 7.77508L12.598 0.295242Z"
                    fill={color}
                    fillRule="evenodd"
                    clipRule="evenodd"
                />
            </Svg>
        </Animated.View>
    );
});

const STARS_CONFIG = [
    {
        id: 1,
        size: 18,
        top: '65%' as const,
        left: '20%' as const,
        delay: 0,
        duration: 1200
    },
    {
        id: 2,
        size: 28,
        top: '25%' as const,
        left: '72%' as const,
        delay: 200,
        duration: 1400
    },
    {
        id: 3,
        size: 16,
        top: '32%' as const,
        left: '82%' as const,
        delay: 400,
        duration: 1100
    }
] as const;

export const AnimatedStars = () => {
    const { colors } = useTheme();

    return (
        <View style={styles.container} pointerEvents="none">
            {STARS_CONFIG.map(star => (
                <Star
                    key={star.id}
                    size={star.size}
                    top={star.top}
                    left={star.left}
                    delay={star.delay}
                    duration={star.duration}
                    color={colors.sparkleStar}
                />
            ))}
        </View>
    );
};

const styles = StyleSheet.create({
    container: {
        ...StyleSheet.absoluteFillObject,
        overflow: 'hidden'
    },
    star: {
        position: 'absolute'
    }
});

export default AnimatedStars;
