import { useSocket } from '@/context/SocketProvider';
import { useRouter } from 'next/router';
import React, { useCallback, useEffect, useState } from 'react'
import peer from '@/service/peer';
import { motion } from 'framer-motion';
import { Video, Phone, Users, Send, ArrowLeft } from 'lucide-react';
import VideoPlayer from '@/components/VideoPlayer';
import CallHandleButtons from '@/components/CallHandleButtons';

const RoomPage = () => {
    const socket = useSocket();
    const router = useRouter();
    const { slug } = router.query;

    const [remoteSocketId, setRemoteSocketId] = useState(null);
    const [myStream, setMyStream] = useState(null);
    const [remoteStream, setRemoteStream] = useState(null);
    const [isAudioMute, setIsAudioMute] = useState(false);
    const [isVideoOnHold, setIsVideoOnHold] = useState(false);
    const [callButton, setCallButton] = useState(true);
    const [isSendButtonVisible, setIsSendButtonVisible] = useState(true);
    const [isConnecting, setIsConnecting] = useState(false);
    const [hasJoinedRoom, setHasJoinedRoom] = useState(false);

    // Check if user came from lobby (has proper session) or direct navigation
    useEffect(() => {
        // Check if user has a valid session or email stored (you might want to implement proper session management)
        const hasValidSession = localStorage.getItem('userEmail') || document.referrer.includes('/');
        
        if (!hasValidSession && typeof window !== 'undefined') {
            // User navigated directly to room page without going through lobby
            console.warn('Direct navigation to room detected, redirecting to lobby');
            router.push('/');
            return;
        }
        
        // If user has a session, mark as joined
        setHasJoinedRoom(true);
    }, [router]);

    // Store user email when they join from lobby
    useEffect(() => {
        socket.on("room:join", (data) => {
            if (typeof window !== 'undefined') {
                localStorage.setItem('userEmail', data.email);
                localStorage.setItem('currentRoom', data.room);
            }
        });

        // Listen for socket errors and provide user feedback
        socket.on("error", (error) => {
            console.error('Socket error:', error);
            alert(`Connection Error: ${error.message || 'Something went wrong. Please try again.'}`);
            // Redirect to lobby on error
            router.push('/');
        });

        return () => {
            socket.off("room:join");
            socket.off("error");
        };
    }, [socket, router]);

    const handleUserJoined = useCallback(({ email, id }) => {
        console.log(`User ${email} joined the room!`);
        setRemoteSocketId(id);
    }, []);

    const handleUserLeft = useCallback(({ email }) => {
        console.log(`User ${email} left the room`);
        setRemoteSocketId(null);
        setRemoteStream(null);
    }, []);

    const handleIncomingCall = useCallback(async ({ from, offer }) => {
        setRemoteSocketId(from);
        setIsConnecting(true);
        
        try {
            const stream = await navigator.mediaDevices.getUserMedia({
                audio: true,
                video: true
            });
            setMyStream(stream);

            const ans = await peer.getAnswer(offer);
            socket.emit("call:accepted", { to: from, ans });
        } catch (error) {
            console.error('Error handling incoming call:', error);
            setIsConnecting(false);
        }
    }, [socket]);

    const sendStreams = useCallback(() => {
        if (myStream) {
            for (const track of myStream.getTracks()) {
                peer.peer.addTrack(track, myStream);
            }
            setIsSendButtonVisible(false);
        }
    }, [myStream]);

    const handleCallAccepted = useCallback(({ from, ans }) => {
        peer.setLocalDescription(ans);
        console.log("Call Accepted");
        setIsConnecting(false);
        sendStreams();
    }, [sendStreams]);

    const handleNegoNeededIncoming = useCallback(async ({ from, offer }) => {
        const ans = await peer.getAnswer(offer);
        socket.emit("peer:nego:done", { to: from, ans });
    }, [socket]);

    const handleNegoNeeded = useCallback(async () => {
        const offer = await peer.getOffer();
        socket.emit("peer:nego:needed", { offer, to: remoteSocketId });
    }, [remoteSocketId, socket]);

    const handleNegoFinal = useCallback(async ({ ans }) => {
        await peer.setLocalDescription(ans);
    }, [])

    useEffect(() => {
        peer.peer.addEventListener('negotiationneeded', handleNegoNeeded);
        return () => {
            peer.peer.removeEventListener('negotiationneeded', handleNegoNeeded);
        }
    }, [handleNegoNeeded]);

    useEffect(() => {
        peer.peer.addEventListener('track', async ev => {
            const remoteStream = ev.streams;
            console.log("GOT TRACKS!");
            setRemoteStream(remoteStream[0]);
            setIsConnecting(false);
        })
    }, [])

    useEffect(() => {
        socket.on("user:joined", handleUserJoined);
        socket.on("user:left", handleUserLeft);
        socket.on("incoming:call", handleIncomingCall);
        socket.on("call:accepted", handleCallAccepted);
        socket.on("peer:nego:needed", handleNegoNeededIncoming);
        socket.on("peer:nego:final", handleNegoFinal);

        return () => {
            socket.off("user:joined", handleUserJoined);
            socket.off("user:left", handleUserLeft);
            socket.off("incoming:call", handleIncomingCall);
            socket.off("call:accepted", handleCallAccepted);
            socket.off("peer:nego:needed", handleNegoNeededIncoming);
            socket.off("peer:nego:final", handleNegoFinal);
        };
    }, [
        socket,
        handleUserJoined,
        handleUserLeft,
        handleIncomingCall,
        handleCallAccepted,
        handleNegoNeededIncoming,
        handleNegoFinal
    ]);

    useEffect(() => {
        socket.on("call:end", ({ from }) => {
            if (from === remoteSocketId) {
                peer.peer.close();

                if (myStream) {
                    myStream.getTracks().forEach(track => track.stop());
                    setMyStream(null);
                }

                setRemoteStream(null);
                setRemoteSocketId(null);
                setCallButton(true);
                setIsSendButtonVisible(true);
                setIsConnecting(false);
            }
        });

        return () => {
            socket.off("call:end");
        }
    }, [remoteSocketId, myStream, socket]);

    useEffect(() => {
        socket.on("call:initiated", ({ from }) => {
            if (from === remoteSocketId) {
                setCallButton(false);
            }
        });

        return () => {
            socket.off("call:initiated");
        }
    }, [socket, remoteSocketId]);

    const handleCallUser = useCallback(async () => {
        setIsConnecting(true);
        
        try {
            const stream = await navigator.mediaDevices.getUserMedia({
                audio: true,
                video: true
            });

            if (isAudioMute) {
                const audioTracks = stream.getAudioTracks();
                audioTracks.forEach(track => track.enabled = false);
            }

            if (isVideoOnHold) {
                const videoTracks = stream.getVideoTracks();
                videoTracks.forEach(track => track.enabled = false);
            }

            const offer = await peer.getOffer();
            socket.emit("user:call", { to: remoteSocketId, offer })
            setMyStream(stream);
            setCallButton(false);
            socket.emit("call:initiated", { to: remoteSocketId });
        } catch (error) {
            console.error('Error starting call:', error);
            setIsConnecting(false);
        }
    }, [remoteSocketId, socket, isAudioMute, isVideoOnHold]);

    const handleToggleAudio = () => {
        if (myStream) {
            const audioTracks = myStream.getAudioTracks();
            audioTracks.forEach(track => track.enabled = !track.enabled);
            setIsAudioMute(!isAudioMute);
        }
    };

    const handleToggleVideo = () => {
        if (myStream) {
            const videoTracks = myStream.getVideoTracks();
            videoTracks.forEach(track => track.enabled = !track.enabled);
            setIsVideoOnHold(!isVideoOnHold);
        }
    }

    const handleEndCall = useCallback(() => {
        peer.peer.close();

        if (myStream) {
            myStream.getTracks().forEach(track => track.stop());
            setMyStream(null);
        }

        setRemoteStream(null);
        setCallButton(true);
        setIsSendButtonVisible(true);
        setIsConnecting(false);

        if (remoteSocketId) {
            socket.emit("call:end", { to: remoteSocketId });
        }
        setRemoteSocketId(null);
    }, [myStream, remoteSocketId, socket]);

    const handleGoBack = () => {
        handleEndCall();
        
        // Clear session data when leaving room
        if (typeof window !== 'undefined') {
            localStorage.removeItem('userEmail');
            localStorage.removeItem('currentRoom');
        }
        
        router.push('/');
    };

    return (
        <>
            {!hasJoinedRoom ? (
                <div className="min-h-screen bg-gradient-to-br from-gray-900 via-blue-900 to-indigo-900 flex items-center justify-center">
                    <div className="text-center text-white">
                        <div className="animate-spin rounded-full h-8 w-8 border-2 border-white border-t-transparent mx-auto mb-4"></div>
                        <p>Verifying access...</p>
                    </div>
                </div>
            ) : (
                <div className='min-h-screen bg-gradient-to-br from-gray-900 via-blue-900 to-indigo-900 relative overflow-hidden'>
            <title>Room {slug} - VideoPeersJS</title>
            
            {/* Background decorative elements */}
            <div className="absolute inset-0 overflow-hidden pointer-events-none">
                <div className="absolute top-1/4 -left-4 w-72 h-72 bg-blue-500 rounded-full mix-blend-multiply filter blur-xl opacity-10 animate-pulse"></div>
                <div className="absolute bottom-1/4 -right-4 w-72 h-72 bg-purple-500 rounded-full mix-blend-multiply filter blur-xl opacity-10 animate-pulse delay-1000"></div>
            </div>

            {/* Header */}
            <motion.header 
                className="absolute top-0 left-0 right-0 z-20 p-6"
                initial={{ opacity: 0, y: -20 }}
                animate={{ opacity: 1, y: 0 }}
                transition={{ duration: 0.6 }}
            >
                <div className="flex items-center justify-between">
                    <div className="flex items-center space-x-4">
                        <motion.button
                            onClick={handleGoBack}
                            className="flex items-center space-x-2 px-4 py-2 bg-white/10 backdrop-blur-sm rounded-xl text-white hover:bg-white/20 transition-all duration-200"
                            whileHover={{ scale: 1.05 }}
                            whileTap={{ scale: 0.95 }}
                        >
                            <ArrowLeft className="h-4 w-4" />
                            <span>Back</span>
                        </motion.button>
                        
                        <div className="flex items-center space-x-2">
                            <Video className="h-6 w-6 text-indigo-400" />
                            <h1 className="text-xl font-bold text-white">
                                {process.env.NEXT_PUBLIC_APP_NAME || 'VideoPeersJS'}
                            </h1>
                        </div>
                    </div>

                    <div className="flex items-center space-x-4">
                        <div className="flex items-center space-x-2 px-4 py-2 bg-white/10 backdrop-blur-sm rounded-xl text-white">
                            <Users className="h-4 w-4" />
                            <span className="text-sm">Room {slug}</span>
                        </div>
                    </div>
                </div>
            </motion.header>

            {/* Connection Status */}
            <motion.div 
                className="absolute top-24 left-1/2 transform -translate-x-1/2 z-20"
                initial={{ opacity: 0, y: -20 }}
                animate={{ opacity: 1, y: 0 }}
                transition={{ duration: 0.6, delay: 0.2 }}
            >
                <div className={`px-6 py-3 rounded-full backdrop-blur-sm text-white text-center ${
                    remoteSocketId ? 'bg-green-500/20 border border-green-400/30' : 'bg-orange-500/20 border border-orange-400/30'
                }`}>
                    <p className="text-sm font-medium">
                        {isConnecting ? (
                            <span className="flex items-center space-x-2">
                                <div className="animate-spin rounded-full h-4 w-4 border-2 border-white border-t-transparent"></div>
                                <span>Connecting...</span>
                            </span>
                        ) : remoteSocketId ? (
                            "🟢 Connected with remote user"
                        ) : (
                            "🟡 Waiting for someone to join..."
                        )}
                    </p>
                </div>
            </motion.div>

            {/* Video Container */}
            <div className="relative h-screen flex items-center justify-center p-6 pt-32">
                {/* Remote Stream (Main) */}
                {remoteStream ? (
                    <VideoPlayer 
                        stream={remoteStream} 
                        name={"Remote Stream"} 
                        isAudioMute={false}
                    />
                ) : (
                    <motion.div 
                        className="w-full max-w-4xl aspect-video bg-gradient-to-br from-gray-800 to-gray-900 rounded-2xl border-2 border-white/10 flex items-center justify-center"
                        initial={{ opacity: 0, scale: 0.8 }}
                        animate={{ opacity: 1, scale: 1 }}
                        transition={{ duration: 0.6 }}
                    >
                        <div className="text-center text-white/60">
                            <Users className="h-24 w-24 mx-auto mb-4 opacity-40" />
                            <p className="text-xl font-medium mb-2">Waiting for remote video...</p>
                            <p className="text-sm">Share this room ID with someone to start a call</p>
                        </div>
                    </motion.div>
                )}

                {/* My Stream (Picture-in-Picture) */}
                {myStream && (
                    <VideoPlayer 
                        stream={myStream} 
                        name={"My Stream"} 
                        isAudioMute={isAudioMute}
                    />
                )}
            </div>

            {/* Action Buttons */}
            <div className="absolute bottom-8 left-1/2 transform -translate-x-1/2 z-30">
                {remoteStream && isSendButtonVisible && (
                    <motion.button
                        onClick={sendStreams}
                        className="mb-4 flex items-center space-x-2 px-6 py-3 bg-green-500 hover:bg-green-600 text-white rounded-xl font-semibold transition-all duration-200"
                        whileHover={{ scale: 1.05 }}
                        whileTap={{ scale: 0.95 }}
                        initial={{ opacity: 0, y: 20 }}
                        animate={{ opacity: 1, y: 0 }}
                    >
                        <Send className="h-5 w-5" />
                        <span>Send Stream</span>
                    </motion.button>
                )}

                {remoteSocketId && callButton && !remoteStream && (
                    <motion.button
                        onClick={handleCallUser}
                        disabled={isConnecting}
                        className="flex items-center space-x-2 px-8 py-4 bg-gradient-to-r from-green-500 to-emerald-500 hover:from-green-600 hover:to-emerald-600 text-white rounded-2xl font-semibold text-lg shadow-lg disabled:opacity-50 disabled:cursor-not-allowed transition-all duration-200"
                        whileHover={{ scale: isConnecting ? 1 : 1.05 }}
                        whileTap={{ scale: isConnecting ? 1 : 0.95 }}
                        initial={{ opacity: 0, y: 20 }}
                        animate={{ opacity: 1, y: 0 }}
                    >
                        {isConnecting ? (
                            <>
                                <div className="animate-spin rounded-full h-6 w-6 border-2 border-white border-t-transparent"></div>
                                <span>Connecting...</span>
                            </>
                        ) : (
                            <>
                                <Phone className="h-6 w-6" />
                                <span>Start Call</span>
                            </>
                        )}
                    </motion.button>
                )}
            </div>

            {/* Call Control Buttons */}
            {myStream && remoteStream && !isSendButtonVisible && (
                <CallHandleButtons
                    isAudioMute={isAudioMute}
                    isVideoOnHold={isVideoOnHold}
                    onToggleAudio={handleToggleAudio}
                    onToggleVideo={handleToggleVideo}
                    onEndCall={handleEndCall}
                />
            )}
        </div>
            )}
        </>
    )
}

export default RoomPage;