/* eslint-disable @typescript-eslint/no-explicit-any */
'use client'
import { CameraIcon, HdIcon, MicrochipIcon, Server, VideoIcon } from 'lucide-react';
import Peer, { DataConnection } from 'peerjs';
import React, { ReactNode, useCallback, useEffect, useRef, useState } from 'react'

type FlowStateType = {
    color: 'red' | 'blue' | 'green' | 'orange',
    flow: 'MIC' | 'VIDEO' | 'SERVER' | 'NO_PEERS' | 'ROOM',
    loading: boolean
}

export default function WebRTCChatUsingPeer() {
    let mediaStream
    // UI

    // const [flowSection, setFlowSection] = useState<'MIC' | 'VIDEO' | 'SERVER'>('MIC')
    const [flowState, setFlowState] = useState<FlowStateType>({
        color: 'blue',
        flow: 'SERVER',
        loading: false
    })


    // const [flow, setFlow] = useState<{
    //     screen: ReactNode,
    //     loading: boolean,
    //     color: 'red' | 'blue' | 'green' | 'orange',
    //     options?: any
    // }[]>([
    //     //     {
    //     //     loading: false,
    //     //     screen: <SelectMicrophone setLoading={setLoading} />,
    //     //     color: 'orange',
    //     //     options: [{
    //     //         label: 'Next',
    //     //         onSelect: (a: any) => { }
    //     //     }]
    //     // }, 
    //     {
    //         loading: false,
    //         screen: <>
    //             <CameraIcon size={45} />
    //             Select video device
    //             <select>
    //                 <option>Select</option>
    //             </select>
    //         </>,
    //         color: 'orange'
    //     }, {
    //         loading: true,
    //         screen: <ConnectingToSerever />,
    //         color: 'blue'
    //     }])


    const peerRef = useRef<Peer>(undefined)
    const [peers, setPeers] = useState<string[]>([])


    const connection = useRef<DataConnection>(undefined)
    const videoRef = useRef<HTMLVideoElement>(null)
    // const [mediaStream, setMediaStream] = useState<MediaStream>(null)
    const [received, setReceivved] = useState<string>('')
    const [peerId, setPeerId] = useState<string>('')
    const [removepeerId, setRemovePeerId] = useState<string>('')
    const [theirPeerId, setTheirPeerId] = useState<string>('')
    const [myStream, setMyStream] = useState<MediaStream|null>(null);

    const [devices, setDevices] = useState<MediaDeviceInfo[]>([])
    const [selectedDevice, setSelectedDevice] = useState<{ video: { deviceId: { exact: string } }, audio: { deviceId: { exact: string } } }>()

    const handleFindPeers = () => {
        peerRef.current?.listAllPeers(peers => {
            setPeers(() => peers)
            console.log(`PEERS`, peers)
            if (peers.length > 1) {
                console.log(`CONNECT TO: `, peers.filter(a => a !== peerId)[0])
                if (!connection.current) {
                    connection.current = peerRef.current?.connect(peers.filter(a => a !== peerId)[0])
                    setRemovePeerId(() => peers.filter(a => a !== peerId)[0])
                }
                setFlowState(s => { return { ...s, flow: 'ROOM', color: 'blue', loading: true } })
            } else {
                setFlowState(s => { return { ...s, flow: 'NO_PEERS', color: 'blue', loading: true } })
            }
        })
    }

    const handleConnectServer = () => {
        setFlowState(s => { return { ...s, flow: 'SERVER' } })

        peerRef.current = new Peer({
            host: "localhost",
            port: 4000,
            path: "/myapp",
            secure: false, // Use true with HTTPS
        })

        // peerRef.current.socket.on('message')
        peerRef.current.on("open", function (id) {
            setPeerId(id)
            setFlowState(s => { return { ...s, color: 'green', loading: false } })
            console.log("My peer ID is: " + id, 'Connected Peers:',);
            handleFindPeers()
        });

        peerRef.current.on('error', function (err) {
            setFlowState(s => { return { ...s, color: 'red', loading: false } })
        })
        peerRef.current.on('close', function () {
            console.log(`Closing connection`)
        })
        peerRef.current.on('connection', function (conn) {
            console.log(`Got Connection`, conn)
            // handleFindPeers()
            setFlowState(s => { return { ...s, flow: 'ROOM' } })
            connection.current!.on("data", function (data) {
                // setReceivved(data as string)
                console.log("Received", data);
            });
            conn.send("Hello!");
        });
    }

    useEffect(() => {
        handleConnectServer()
    }, [])


    // const peer = new Peer({
    //     host: "localhost",
    //     port: 4000,
    //     path: "/myapp",
    //     secure: false, // Use true with HTTPS
    // });


    // useEffect(() => {
    //     peer.on("open", function (id) {
    //         setPeerId(id)
    //         console.log("My peer ID is: " + id);
    //     });
    // }, [])


    // peer.on('connection', function (conn) {
    //     console.log(`Got Connection`, conn)
    //     conn.on("data", function (data) {
    //         setReceivved(data as string)
    //         console.log("Received", data);
    //     });
    //     conn.send("Hello!");
    // });
    // useEffect(() => {
    //     // Get user media
    //     navigator.mediaDevices.getUserMedia({ video: true, audio: true })
    //         .then(stream => {
    //             // setMyStream(stream);
    //             // if (videoRef.current) {
    //             //     videoRef.current.srcObject = stream;
    //             // }
    //         })
    //         .catch(err => console.error("Failed to get local stream", err));

    //     // Initialize PeerJS
    //     // const peer = new Peer(); // PeerJS manages server connection
    //     // currentPeer.current = peer;

    //     peer.on('open', (id) => {
    //         setPeerId(id);
    //         console.log('My peer ID is:', id);
    //     });

    //     // Listen for incoming calls
    //     peer.on('call', (call) => {
    //         if (myStream) {
    //             // Answer the call with your stream
    //             call.answer(myStream);
    //             call.on('stream', (remoteStream) => {
    //                 // Show stream in remote video element
    //                 if (videoRef.current) {
    //                     videoRef.current.srcObject = remoteStream;
    //                 }
    //             });
    //         }
    //     });

    //     peer.on('error', (err) => console.error(err));

    //     return () => {
    //         if (peer) {
    //             peer.destroy();
    //         }
    //     };
    // }, [myStream]);


    // useEffect(() => {
    //     const load = async () => {
    //         // Load media devices
    //         const res = await navigator.mediaDevices.getUserMedia({ video: true, audio: true })
    //         // .then(async res =>
    //         setDevices(await navigator.mediaDevices.enumerateDevices())
    //         // )
    //         // setFlowIdx(1)
    //         // setFlowIdx(2)

    //         // console.log(await navigator.mediaDevices.enumerateDevices())
    //         // console.log(await navigator.mediaDevices.getUserMedia().)
    //     }
    //     load()
    //     peer.on("call", function (call) {
    //         alert(`You have a call`)
    //         // Answer the call, providing our mediaStream
    //         // if (mediaStream) {
    //         call.answer(mediaStream);

    //         call.on('stream', (remoteStream) => {
    //             // Show stream in remote video element
    //             if (videoRef.current) {
    //                 videoRef.current.srcObject = remoteStream;
    //             }
    //         });
    //         // }
    //     });
    // }, [])

    if (flowState.flow === 'ROOM') {
        return <div className='flex flex-col w-screen h-screen'>
            <div className='flex justify-between w-full flex-col'>
                <div>LOCAL PEER:{peerId}</div>
                <div>REMOVE PEER:{removepeerId}</div>
            </div>
            <div className='grow'></div>
            <form onSubmit={(form) => {
                form.preventDefault()
                const formData = new FormData(form.target);
                // const det = Object.fromEntries(formData.entries())
                try {
                    console.log(`Sending:`, connection.current, formData.get('message') as string)
                    connection.current?.send(formData.get('message') as string)
                } catch (e) {
                    console.error('Failed to send message', e)
                }
            }}>
                <input name='message' placeholder='message' />
                <button type='submit'>Send</button>
            </form>
        </div>
    }
    return (<Screen
        color={flowState.color}
        loading={flowState.loading}>
        {
            {
                'MIC': <SelectMicrophone setFlowState={setFlowState}
                    onChange={e => {
                        setSelectedDevice((d: any) => {
                            return { ...d, audio: { deviceId: { exact: e } } }
                        })
                        setFlowState(s => { return { ...s, flow: 'VIDEO' } })
                        // setFlowSection('VIDEO')
                    }}
                />,
                'VIDEO': <SelectVideo setFlowState={setFlowState}
                    onChange={e => {
                        setSelectedDevice((d: any) => {
                            return { ...d, video: { deviceId: { exact: e } } }
                        })
                        handleConnectServer()
                    }}
                />,
                'SERVER': <ConnectingToSerever
                    setFlowState={setFlowState}
                />,
                'NO_PEERS': <>Waiting for others to join</>,
                'ROOM': <></>
            }[flowState.flow]
        }
        {/* {flow[flowIdx].screen} */}
    </Screen>)
    // return (
    //     <div>
    //         {JSON.stringify(peerId)}
    //         <div>
    //             <b>Settings</b>
    //             <b>Video</b>
    //             {devices.filter(a => a.kind === 'videoinput').map(device =>
    //                 <div key={device.deviceId}
    //                     onClick={() => setSelectedDevice((d: any) => {
    //                         return { ...d, video: { deviceId: { exact: device.deviceId } } }
    //                     })}
    //                     className={`${selectedDevice && selectedDevice.video && device.deviceId === selectedDevice?.video.deviceId.exact ? 'bg-green-300' : ''}`}
    //                 >
    //                     {device.label}
    //                 </div>
    //             )}
    //             <b>Audio</b>
    //             {devices.filter(a => a.kind === 'audioinput').map(device =>
    //                 <div key={device.deviceId}
    //                     onClick={() => setSelectedDevice((d: any) => {
    //                         return { ...d, audio: { deviceId: { exact: device.deviceId } } }
    //                     })}
    //                     className={`${selectedDevice && selectedDevice.audio && device.deviceId === selectedDevice?.audio.deviceId.exact ? 'bg-green-300' : ''}`}

    //                 >
    //                     {device.label}
    //                 </div>
    //             )}
    //         </div>
    //         <input placeholder='Cannect to' onChange={e => setTheirPeerId(e.target.value)} />
    //         <button onClick={() => {
    //             console.log(`Connecting`)
    //             connection.current
    //                 = peer.connect(theirPeerId, {

    //                 });
    //         }}>Start</button>
    //         <button
    //             className='p-2'
    //             onClick={() => {
    //                 // const stream = await navigator.mediaDevices.getUserMedia({ audio: true, video: true });

    //                 navigator.mediaDevices.getUserMedia(selectedDevice)
    //                     .then(stream => peer.call(theirPeerId, stream))
    //                 // const call = peer.call(theirPeerId, stream);

    //                 //                  const stream = await navigator.mediaDevices.getUserMedia({
    //                 //     video: { deviceId: { exact: selectedVideoId } }
    //                 //   });
    //             }}
    //         >Call</button>
    //         <textarea onChange={e => connection.current?.send(e.target.value)} placeholder='Message' rows={6} />
    //         {JSON.stringify(received)}
    //         <video ref={videoRef} />
    //     </div>
    // )
}


export function Screen({ color, loading, children }: {
    color: 'red' | 'blue' | 'green' | 'orange',
    loading: boolean
    children: ReactNode
}) {
    return <div
        style={{
            background: color == 'orange' ? '#441306' : color == 'green' ? '#032e15' : color == 'red' ? '#460809' : '#162456'
        }}
        className={`h-screen w-screen flex items-center align-middle justify-center`}>
        <>
            <div className='relative  '>
                {/* <div className='absolute flex items-center align-middle justify-center -left-20 -top-10 bg-blue-900 hover:bg-blue-800 shadow shadow-white shadow-2xl rounded-full grow w-64 h-64'>
                        ITEM 1
                    </div>
                    <div className='absolute right-0 bg-blue-950 hover:bg-blue-900 w-64 h-64'>
                        ITEM 2
                    </div>
                    <div className='absolute bottom-0 bg-blue-950 hover:bg-blue-900'>
                        ITEM 3
                    </div> */}
                <div
                    style={{
                        background: color == 'orange' ?
                            'radial-gradient(circle, oklch(40.8% 0.123 38.172) 0%, rgba(0,0,0,0.3) 100%)'
                            : color == 'green' ?
                                'radial-gradient(circle, oklch(39.3% 0.095 152.535) 0%, rgba(0,0,0,0.3) 100%)' :
                                color == 'red' ?
                                    'radial-gradient(circle,oklch(39.6% 0.141 25.723) 0%, rgba(0,0,0,0.3) 100%)'
                                    :
                                    'radial-gradient(circle,oklch(37.9% 0.146 265.522) 0%, rgba(0,0,0,0.3) 100%)'

                    }}
                    className={`w-96 h-95 rounded-full relative  border-8 shadow-lg  ${loading && `animate-spin shadow-purple-300/75`}  text-3xl text-white flex items-center justify-center align-middle `}>
                    <div className="absolute inset-0 flex items-center justify-center animate-[inherit] direction-reverse">
                        <span className="flex gap-2 flex-col items-center font-bold text-white text-shadow-white text-shadow-2xs">
                            {children}
                        </span>
                    </div>
                </div>
            </div>
        </>
    </div>
}

export function ConnectingToSerever({
    setFlowState,
}: {
    setFlowState: React.Dispatch<React.SetStateAction<FlowStateType>>
}) {
    useEffect(() => { setFlowState(s => { return { ...s, color: 'blue', loading: true } }) }, [])


    // const peerConn = useCallback(() => {

    //     const peer = new Peer({
    //         host: "localhost",
    //         port: 4000,
    //         path: "/myapp",
    //         secure: false, // Use true with HTTPS
    //     });
    //     peer.on("open", function (id) {
    //         setPeerId(id)
    //         setColor('green')
    //         console.log("My peer ID is: " + id);
    //     });

    //     peer.on('error', function (err) {
    //         setColor('red')
    //         setLoading(false)
    //     })

    //     peer.on('connection', function (conn) {
    //         console.log(`Got Connection`, conn)
    //         conn.on("data", function (data) {
    //             // setReceivved(data as string)
    //             console.log("Received", data);
    //         });
    //         conn.send("Hello!");
    //     });
    // }, [])

    // useEffect(() => {
    //     const load = async () => {
    //         peer.on("open", function (id) {
    //             setPeerId(id)
    //             setColor('green')
    //             console.log("My peer ID is: " + id);
    //         });

    //         peer.on('error', function (err) {
    //             setColor('red')
    //             setLoading(false)
    //         })

    //         peer.on('connection', function (conn) {
    //             console.log(`Got Connection`, conn)
    //             conn.on("data", function (data) {
    //                 // setReceivved(data as string)
    //                 console.log("Received", data);
    //             });
    //             conn.send("Hello!");
    //         });

    //     }
    //     setColor('green')
    //     setLoading(true)
    //     load()
    // }, [])
    return <>
        <Server size={45} />
        Connecting to Server
    </>
}

export function SelectMicrophone({
    setFlowState,
    onChange
}: {
    setFlowState: React.Dispatch<React.SetStateAction<FlowStateType>>
    onChange: (device: string) => void
}) {
    const [devices, setDevices] = useState<MediaDeviceInfo[]>([])
    useEffect(() => {
        const load = async () => {
            // Load media devices
            // setTimeout(() => setLoading(false), 3000)
            // setLoading(false)
            const res = await navigator.mediaDevices.getUserMedia({ video: true, audio: true })
            // // .then(async res =>
            setDevices(await navigator.mediaDevices.enumerateDevices())

            setFlowState(s => { return { ...s, color: 'orange', loading: false } })
        }
        setFlowState(s => { return { ...s, color: 'green', loading: true } })
        load()
    }, [])
    return <>
        <MicrochipIcon size={45} />
        {
            devices.length == 0 ? 'Finding Audio Devices' : <>

                Select audio device
                <select className='text-sm w-64 bg-white p-2 text-black'
                    onChange={e => onChange(e.target.value)}
                >
                    <option>Select</option>
                    {devices.filter(a => a.kind === 'audioinput').map((device, i) =>
                        <option key={`device-${i}`} value={device.deviceId}>{device.label}</option>
                    )}

                </select>
            </>
        }
    </>
}

export function SelectVideo({
    setFlowState,
    onChange
}: {
    setFlowState: React.Dispatch<React.SetStateAction<FlowStateType>>
    onChange: (device: string) => void
}) {
    const [devices, setDevices] = useState<MediaDeviceInfo[]>([])
    useEffect(() => {
        const load = async () => {
            // Load media devices
            // setTimeout(() => setLoading(false), 3000)
            // setLoading(false)
            const res = await navigator.mediaDevices.getUserMedia({ video: true, audio: true })
            // // .then(async res =>
            setDevices(await navigator.mediaDevices.enumerateDevices())
            setFlowState(s => { return { ...s, color: 'orange', loading: false } })
        }
        setFlowState(s => { return { ...s, color: 'green', loading: true } })
        load()
    }, [])
    return <>
        <VideoIcon size={45} />
        {
            devices.length == 0 ? 'Finding Video Devices' : <>

                Select video device
                <select className='text-sm w-64 bg-white p-2 text-black'
                    onChange={e => onChange(e.target.value)}
                >
                    <option>Select</option>
                    {devices.filter(a => a.kind === 'videoinput').map((device, i) =>
                        <option key={`device-${i}`} value={device.deviceId}>{device.label}</option>
                    )}

                </select>
            </>
        }
    </>
}