import { useEffect, useRef, useState, useCallback } from 'react';
import { useLocation } from 'react-router-dom';
import { useAudio } from '../contexts/AudioContext';
import { isElectronApp } from '../utils/assetPath';

export default function BackgroundMusic() {
    const { pathname } = useLocation();
    const { audioContext, masterVolume, musicVolume, isMuted, getAudioBuffer } = useAudio();

    // We only need refs for the source (track) and the gain (volume)
    // The context is now shared.
    const sourceNodeRef = useRef<AudioBufferSourceNode | null>(null);
    const musicGainNodeRef = useRef<GainNode | null>(null);

    const [audioBuffer, setAudioBuffer] = useState<AudioBuffer | null>(null);
    const [isLoading, setIsLoading] = useState(true);
    const [playbackError, setPlaybackError] = useState(false);

    // Routes where music should play
    const shouldPlayMusic = useCallback(() => {
        // Game main view
        if (pathname === '/game') return true;
        // Leaderboards
        if (pathname === '/leaderboards') return true;
        // Account management
        if (pathname === '/account') return true;
        // Profile views
        if (pathname.startsWith('/profile/')) return true;

        return false;
    }, [pathname]);

    // Calculate effective volume
    const effectiveVolume = isMuted ? 0 : masterVolume * musicVolume;

    // Load Audio Buffer (using shared cache)
    useEffect(() => {
        const loadAudio = async () => {
            setIsLoading(true);
            const src = isElectronApp() ? './audio/bgm.wav' : '/audio/bgm.wav';
            const buffer = await getAudioBuffer(src);
            if (buffer) {
                setAudioBuffer(buffer);
            } else {
                console.error('Failed to load background music buffer');
                setPlaybackError(true);
            }
            setIsLoading(false);
        };

        if (audioContext) {
            loadAudio();
        }
    }, [audioContext, getAudioBuffer]);

    // Setup Gain Node
    useEffect(() => {
        if (audioContext && !musicGainNodeRef.current) {
            const gain = audioContext.createGain();
            gain.connect(audioContext.destination);
            musicGainNodeRef.current = gain;
        }
    }, [audioContext]);

    // Playback Logic
    const playMusic = useCallback(() => {
        if (!audioContext || !audioBuffer || !musicGainNodeRef.current) return;

        // If already playing, do nothing
        if (sourceNodeRef.current) return;

        try {
            // Ensure context is running (handled globally but good to check)
            if (audioContext.state === 'suspended') {
                audioContext.resume().catch(e => console.warn(e));
            }

            const source = audioContext.createBufferSource();
            source.buffer = audioBuffer;
            source.loop = true;
            source.connect(musicGainNodeRef.current);
            source.start(0);
            sourceNodeRef.current = source;
            setPlaybackError(false);

            // Cleanup on end (though looping, so only if loop=false or stopped)
            source.onended = () => {
                if (sourceNodeRef.current === source) {
                    sourceNodeRef.current = null;
                }
            };

        } catch (error) {
            console.error('Start playback failed:', error);
            setPlaybackError(true);
        }
    }, [audioContext, audioBuffer]);

    const stopMusic = useCallback(() => {
        if (sourceNodeRef.current) {
            try {
                sourceNodeRef.current.stop();
                sourceNodeRef.current.disconnect();
            } catch (e) {
                // ignore
            }
            sourceNodeRef.current = null;
        }
    }, []);

    // Handle Volume Changes
    useEffect(() => {
        if (musicGainNodeRef.current && audioContext) {
            const currentTime = audioContext.currentTime;
            musicGainNodeRef.current.gain.setTargetAtTime(effectiveVolume, currentTime, 0.1);
        }
    }, [effectiveVolume, audioContext]);

    // Control Play/Stop based on Route and Readiness
    useEffect(() => {
        if (isLoading || !audioContext) return;

        const handleAudioLogic = () => {
            if (shouldPlayMusic()) {
                if (!sourceNodeRef.current) {
                    playMusic();
                }
            } else {
                stopMusic();
            }
        };

        handleAudioLogic();

    }, [shouldPlayMusic, isLoading, audioContext, playMusic, stopMusic]);

    // Cleanup on unmount
    useEffect(() => {
        return () => {
            stopMusic();
            // Don't close context, it's shared
        };
    }, [stopMusic]);

    // Monitor state for overlay
    const [isSuspended, setIsSuspended] = useState(false);
    useEffect(() => {
        if (!audioContext) return;

        const updateState = () => setIsSuspended(audioContext.state === 'suspended');
        updateState();

        const interval = setInterval(updateState, 1000);
        audioContext.addEventListener('statechange', updateState);

        return () => {
            clearInterval(interval);
            audioContext.removeEventListener('statechange', updateState);
        };
    }, [audioContext]);

    // Render overlay if music should play but is blocked
    if (!shouldPlayMusic()) return null;

    // If not suspended and no error, don't show overlay
    if (!isSuspended && !playbackError) return null;

    return (
        <div
            style={{
                position: 'fixed',
                bottom: '20px',
                right: '20px',
                zIndex: 9999,
                background: 'rgba(255, 74, 74, 0.9)',
                color: 'white',
                padding: '10px 20px',
                borderRadius: '8px',
                cursor: 'pointer',
                boxShadow: '0 4px 6px rgba(0,0,0,0.3)',
                fontWeight: 'bold',
                animation: 'pulse 2s infinite'
            }}
            onClick={() => {
                if (audioContext) {
                    audioContext.resume().then(() => {
                        // Attempt to play again
                        playMusic();
                    });
                }
            }}
        >
            {playbackError ? '⚠️ Audio Error' : '🎵 Click to Enable Audio'}
        </div>
    );
}
