import { useEffect, useRef, useState, useMemo } from 'react';
import { motion, useAnimation } from 'framer-motion';

const NUM_DUPLICATES = 5; // How many loops for the spin effect

// Fisher-Yates shuffle algorithm
const shuffleArray = (array) => {
    const shuffled = [...array];
    for (let i = shuffled.length - 1; i > 0; i--) {
        const j = Math.floor(Math.random() * (i + 1));
        [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
    }
    return shuffled;
};

// Responsive slot heights based on screen size
const getSlotHeight = () => {
    if (typeof window === 'undefined') return 320;
    const width = window.innerWidth;
    if (width < 640) return 96;   // mobile (h-24)
    if (width < 768) return 128;  // sm (h-32)
    if (width < 1024) return 176; // md (h-44)
    if (width < 1280) return 224; // lg (h-56)
    if (width < 1536) return 288; // xl (h-72)
    return 320; // 2xl (h-80)
};

export function SlotMachine({ winner, isSpinning, onAnimationComplete, onDraw, poolLength }) {
    const controls1 = useAnimation();
    const controls2 = useAnimation();
    const controls3 = useAnimation();
    const [slotHeight, setSlotHeight] = useState(getSlotHeight());

    // Generate randomized sequences for each reel (memoized so they stay consistent)
    // Always start with 0 at position 0, then shuffle the rest
    const randomSequences = useMemo(() => {
        // First reel (hundreds): only 0 and 1
        const createSequenceFirstReel = () => {
            const remaining = [1];
            const shuffled = shuffleArray(remaining);
            return [0, ...shuffled]; // Always put 0 first, then 1
        };

        // Second and third reels: 0-9
        const createSequence = () => {
            const remaining = [1, 2, 3, 4, 5, 6, 7, 8, 9];
            const shuffled = shuffleArray(remaining);
            return [0, ...shuffled]; // Always put 0 first
        };

        return [
            createSequenceFirstReel(), // Reel 1: [0, 1]
            createSequence(),          // Reel 2: [0, 1-9 shuffled]
            createSequence(),          // Reel 3: [0, 1-9 shuffled]
        ];
    }, []);

    useEffect(() => {
        const handleResize = () => setSlotHeight(getSlotHeight());
        window.addEventListener('resize', handleResize);
        return () => window.removeEventListener('resize', handleResize);
    }, []);

    useEffect(() => {
        if (isSpinning && winner !== null) {
            const digits = winner.toString().padStart(3, '0').split('').map(Number);
            animateReels(digits);
        }
    }, [isSpinning, winner]);

    const animateReels = async (digits) => {
        // Reset positions instantly
        await Promise.all([
            controls1.set({ y: 0 }),
            controls2.set({ y: 0 }),
            controls3.set({ y: 0 })
        ]);

        // Animate each reel with stagger
        // For each digit, find its position in the randomized sequence
        const spin = (control, digit, reelIndex, delay) => {
            // Find where this digit appears in the last cycle of the randomized sequence
            const lastCycleStart = NUM_DUPLICATES * 10;
            const digitIndexInSequence = randomSequences[reelIndex].indexOf(digit);
            const targetIndex = lastCycleStart + digitIndexInSequence;
            const targetY = -(targetIndex * slotHeight);

            return control.start({
                y: targetY,
                transition: {
                    duration: 20 + delay,
                    ease: [0.1, 0.9, 0.2, 1], // "Luxury" ease-out
                    delay: 0 // We can rely on duration difference for staggering or explicit delay
                }
            });
        };

        // Staggered finish times: 20s, 20.5s, 21s
        await Promise.all([
            spin(controls1, digits[0], 0, 0),
            spin(controls2, digits[1], 1, 0.5),
            spin(controls3, digits[2], 2, 1.0)
        ]);

        if (onAnimationComplete) {
            onAnimationComplete();
        }
    };

    const Strip = ({ controls, reelIndex }) => {
        // Generate the number strip with randomized sequence
        const numbers = [];
        const sequence = randomSequences[reelIndex];

        // For the first reel (only 0-1), we need more repetitions to fill the strip
        // For other reels (0-9), use normal repetitions
        const repetitions = reelIndex === 0
            ? (NUM_DUPLICATES + 1) * 5  // First reel: repeat 30 times (2 numbers × 30 = 60 total)
            : (NUM_DUPLICATES + 1);      // Other reels: repeat 6 times (10 numbers × 6 = 60 total)

        for (let i = 0; i < repetitions; i++) {
            sequence.forEach(num => numbers.push(num));
        }

        return (
            <motion.div
                className="flex flex-col items-center w-full"
                animate={controls}
            >
                {numbers.map((num, i) => (
                    <div
                        key={i}
                        className="flex items-center justify-center font-black relative"
                        style={{
                            height: slotHeight,
                            width: '100%',
                            fontSize: `${slotHeight * 0.78}px`,
                            fontWeight: 'bold',
                            fontFamily: 'system-ui, -apple-system, sans-serif',
                            background: 'linear-gradient(to bottom, #bf953f 0%, #fcf6ba 40%, #b38728 55%, #fbf5b7 100%)',
                            WebkitBackgroundClip: 'text',
                            WebkitTextFillColor: 'transparent',
                            backgroundClip: 'text',
                            filter: 'drop-shadow(0 4px 8px rgba(0, 0, 0, 0.3))',
                            lineHeight: '1',
                        }}
                    >
                        {num}
                    </div>
                ))}
            </motion.div>
        );
    };

    const handleClick = () => {
        if (!isSpinning && poolLength > 0 && onDraw) {
            onDraw();
        }
    };

    return (
        <div
            className={`relative flex items-center justify-center z-20 w-full ${
                !isSpinning && poolLength > 0 ? 'cursor-pointer' : 'cursor-not-allowed'
            }`}
            onClick={handleClick}
        >
            <div className={`flex gap-2 sm:gap-3 md:gap-4 lg:gap-5 xl:gap-6 justify-center transition-transform duration-200 ${
                !isSpinning && poolLength > 0 ? 'hover:scale-105 active:scale-95' : ''
            }`}>
                <SlotBox><Strip controls={controls1} reelIndex={0} /></SlotBox>
                <SlotBox><Strip controls={controls2} reelIndex={1} /></SlotBox>
                <SlotBox><Strip controls={controls3} reelIndex={2} /></SlotBox>
            </div>
        </div>
    );
}

const SlotBox = ({ children }) => (
    <div
        className="relative w-32 h-40 sm:w-40 sm:h-48 md:w-48 md:h-60 lg:w-60 lg:h-[18rem] xl:w-72 xl:h-[22rem] 2xl:w-80 2xl:h-96 flex items-start justify-center overflow-hidden"
        style={{
            borderRadius: '1.5rem',
            background: '#FFFFFF',
            border: '3px solid #D4AF37',
            boxShadow: '0 8px 32px rgba(0, 0, 0, 0.3), 0 0 0 2px #D4AF37'
        }}
    >
        <div className="relative w-full h-full">
            {children}
        </div>
    </div>
);
