import { useEffect, useRef, useState, useCallback } from 'react';
import { motion } from 'framer-motion';
import { Video, VideoOff, Volume2, VolumeX, Maximize2, RefreshCw, Wifi, WifiOff } from 'lucide-react';
import { cn } from '../../lib/utils';

interface VideoPlayerProps {
    streamKey: string;
    className?: string;
    showControls?: boolean;
    autoPlay?: boolean;
    muted?: boolean;
    onError?: (error: Error) => void;
    onStatusChange?: (status: 'connecting' | 'connected' | 'disconnected' | 'error') => void;
}

/**
 * WebRTC video player for go2rtc streams
 * Connects to go2rtc's WebSocket API for low-latency video playback
 */
export function VideoPlayer({
    streamKey,
    className,
    showControls = true,
    autoPlay = true,
    muted = true,
    onError,
    onStatusChange
}: VideoPlayerProps) {
    const videoRef = useRef<HTMLVideoElement>(null);
    const pcRef = useRef<RTCPeerConnection | null>(null);
    const wsRef = useRef<WebSocket | null>(null);

    const [status, setStatus] = useState<'connecting' | 'connected' | 'disconnected' | 'error'>('disconnected');
    const [isMuted, setIsMuted] = useState(muted);
    const [isFullscreen, setIsFullscreen] = useState(false);
    const [reconnectCount, setReconnectCount] = useState(0);

    // go2rtc base URL - uses relative path since it's behind the same domain via Traefik
    const go2rtcBase = '/monitor';

    const updateStatus = useCallback((newStatus: typeof status) => {
        setStatus(newStatus);
        onStatusChange?.(newStatus);
    }, [onStatusChange]);

    const cleanup = useCallback(() => {
        if (wsRef.current) {
            wsRef.current.close();
            wsRef.current = null;
        }
        if (pcRef.current) {
            pcRef.current.close();
            pcRef.current = null;
        }
    }, []);

    const connect = useCallback(async () => {
        cleanup();
        updateStatus('connecting');

        try {
            // Create RTCPeerConnection
            const pc = new RTCPeerConnection({
                iceServers: [
                    { urls: 'stun:stun.l.google.com:19302' }
                ]
            });
            pcRef.current = pc;

            // Handle incoming tracks
            pc.ontrack = (event) => {
                if (videoRef.current && event.streams[0]) {
                    videoRef.current.srcObject = event.streams[0];
                    updateStatus('connected');
                }
            };

            pc.oniceconnectionstatechange = () => {
                if (pc.iceConnectionState === 'disconnected' || pc.iceConnectionState === 'failed') {
                    updateStatus('disconnected');
                }
            };

            // Open WebSocket to go2rtc
            const wsUrl = `${window.location.protocol === 'https:' ? 'wss:' : 'ws:'}//${window.location.host}${go2rtcBase}/api/ws?src=${encodeURIComponent(streamKey)}`;
            const ws = new WebSocket(wsUrl);
            wsRef.current = ws;

            ws.onopen = async () => {
                // Add transceivers for receiving video/audio
                pc.addTransceiver('video', { direction: 'recvonly' });
                pc.addTransceiver('audio', { direction: 'recvonly' });

                // Create and send offer
                const offer = await pc.createOffer();
                await pc.setLocalDescription(offer);

                ws.send(JSON.stringify({
                    type: 'webrtc/offer',
                    value: pc.localDescription?.sdp
                }));
            };

            ws.onmessage = async (event) => {
                const msg = JSON.parse(event.data);

                if (msg.type === 'webrtc/answer') {
                    await pc.setRemoteDescription({
                        type: 'answer',
                        sdp: msg.value
                    });
                } else if (msg.type === 'webrtc/candidate') {
                    if (msg.value) {
                        await pc.addIceCandidate({
                            candidate: msg.value,
                            sdpMid: '0'
                        });
                    }
                }
            };

            ws.onerror = (error) => {
                console.error('WebSocket error:', error);
                updateStatus('error');
                onError?.(new Error('WebSocket connection failed'));
            };

            ws.onclose = () => {
                if (status !== 'error') {
                    updateStatus('disconnected');
                }
            };

            // Send ICE candidates
            pc.onicecandidate = (event) => {
                if (event.candidate && ws.readyState === WebSocket.OPEN) {
                    ws.send(JSON.stringify({
                        type: 'webrtc/candidate',
                        value: event.candidate.candidate
                    }));
                }
            };

        } catch (error) {
            console.error('Failed to connect:', error);
            updateStatus('error');
            onError?.(error as Error);
        }
    }, [streamKey, cleanup, updateStatus, onError, status]);

    // Initial connection
    useEffect(() => {
        if (autoPlay) {
            connect();
        }
        return cleanup;
    }, [streamKey, autoPlay, connect, cleanup]);

    // Reconnect logic
    const handleReconnect = useCallback(() => {
        setReconnectCount(c => c + 1);
        connect();
    }, [connect]);

    const toggleMute = useCallback(() => {
        if (videoRef.current) {
            videoRef.current.muted = !videoRef.current.muted;
            setIsMuted(!isMuted);
        }
    }, [isMuted]);

    const toggleFullscreen = useCallback(() => {
        if (!videoRef.current) return;

        if (!document.fullscreenElement) {
            videoRef.current.requestFullscreen();
            setIsFullscreen(true);
        } else {
            document.exitFullscreen();
            setIsFullscreen(false);
        }
    }, []);

    return (
        <div className={cn(
            "relative overflow-hidden rounded-xl bg-black",
            className
        )}>
            {/* Video Element */}
            <video
                ref={videoRef}
                autoPlay
                playsInline
                muted={isMuted}
                className="w-full h-full object-contain"
            />

            {/* Status Overlay */}
            {status !== 'connected' && (
                <div className="absolute inset-0 flex items-center justify-center bg-black/80">
                    <div className="text-center">
                        {status === 'connecting' && (
                            <motion.div
                                animate={{ rotate: 360 }}
                                transition={{ duration: 1, repeat: Infinity, ease: 'linear' }}
                            >
                                <RefreshCw className="w-8 h-8 text-emerald-400 mx-auto mb-2" />
                            </motion.div>
                        )}
                        {status === 'disconnected' && (
                            <WifiOff className="w-8 h-8 text-gray-400 mx-auto mb-2" />
                        )}
                        {status === 'error' && (
                            <VideoOff className="w-8 h-8 text-red-400 mx-auto mb-2" />
                        )}
                        <p className="text-sm text-gray-400 capitalize">{status}</p>
                        {(status === 'disconnected' || status === 'error') && (
                            <button
                                onClick={handleReconnect}
                                className="mt-3 px-4 py-2 bg-emerald-600 hover:bg-emerald-500 text-white text-sm rounded-lg transition-colors"
                            >
                                Reconnect
                            </button>
                        )}
                    </div>
                </div>
            )}

            {/* Controls Overlay */}
            {showControls && status === 'connected' && (
                <div className="absolute bottom-0 left-0 right-0 p-3 bg-gradient-to-t from-black/80 to-transparent opacity-0 hover:opacity-100 transition-opacity">
                    <div className="flex items-center justify-between">
                        <div className="flex items-center gap-2">
                            <div className="flex items-center gap-1.5 text-xs text-emerald-400">
                                <Wifi size={12} />
                                <span className="font-medium">LIVE</span>
                            </div>
                        </div>
                        <div className="flex items-center gap-2">
                            <button
                                onClick={toggleMute}
                                className="p-2 hover:bg-white/10 rounded-lg transition-colors"
                            >
                                {isMuted ? (
                                    <VolumeX size={18} className="text-white" />
                                ) : (
                                    <Volume2 size={18} className="text-white" />
                                )}
                            </button>
                            <button
                                onClick={toggleFullscreen}
                                className="p-2 hover:bg-white/10 rounded-lg transition-colors"
                            >
                                <Maximize2 size={18} className="text-white" />
                            </button>
                        </div>
                    </div>
                </div>
            )}

            {/* Live indicator */}
            {status === 'connected' && (
                <div className="absolute top-3 left-3 flex items-center gap-1.5 px-2 py-1 bg-red-600 rounded text-xs text-white font-bold">
                    <div className="w-2 h-2 bg-white rounded-full animate-pulse" />
                    LIVE
                </div>
            )}
        </div>
    );
}

/**
 * Fallback MSE player for browsers without WebRTC support
 */
export function VideoPlayerMSE({
    streamKey,
    className,
    showControls = true
}: Omit<VideoPlayerProps, 'autoPlay' | 'muted' | 'onError' | 'onStatusChange'>) {
    const go2rtcBase = '/monitor';
    const mseUrl = `${go2rtcBase}/api/stream.mp4?src=${encodeURIComponent(streamKey)}`;

    return (
        <div className={cn(
            "relative overflow-hidden rounded-xl bg-black",
            className
        )}>
            <video
                src={mseUrl}
                autoPlay
                playsInline
                muted
                controls={showControls}
                className="w-full h-full object-contain"
            />
        </div>
    );
}

export default VideoPlayer;
