import { useState, useEffect, useRef } from 'react';
import { RoomEvent } from 'livekit-client';

export const VideoRenderer = ({ track, style }) => {
    const videoRef = useRef(null);

    useEffect(() => {
        const el = videoRef.current;
        if (el && track) {
            track.attach(el);
            return () => {
                track.detach(el);
            };
        }
    }, [track]);

    return (
        <video
            ref={videoRef}
            style={{ width: '100%', height: '100%', objectFit: 'contain', backgroundColor: 'black', ...style }}
        />
    );
};

export function findTrackPubs(participant) {
    let cameraPub = null;
    let screenSharePub = null;
    let screenShareAudioPub = null;

    const trackMap = participant.tracks || participant.trackPublications;
    if (trackMap) {
        for (const pub of trackMap.values()) {
            const source = pub.source ? pub.source.toString().toLowerCase() : '';
            const name = pub.trackName ? pub.trackName.toLowerCase() : '';

            if (source === 'screen_share_audio' || name === 'screen_share_audio') {
                screenShareAudioPub = pub;
            } else if (source === 'screenshare' || source === 'screen_share' || name.includes('screen')) {
                screenSharePub = pub;
            } else if (source === 'camera' || name.includes('camera')) {
                cameraPub = pub;
            } else if (pub.kind === 'video' && !screenSharePub) {
                screenSharePub = pub;
            }
        }
    }

    // Fallback for older SDKs
    if ((!screenSharePub && !cameraPub) && participant.getTracks) {
        try {
            for (const pub of participant.getTracks()) {
                const source = pub.source ? pub.source.toString().toLowerCase() : '';
                const name = pub.trackName ? pub.trackName.toLowerCase() : '';
                if (source === 'screen_share_audio' || name === 'screen_share_audio') {
                    screenShareAudioPub = pub;
                } else if (source === 'screenshare' || source === 'screen_share' || name.includes('screen')) {
                    screenSharePub = pub;
                } else if (source === 'camera' || name.includes('camera')) {
                    cameraPub = pub;
                } else if (pub.kind === 'video' && !screenSharePub) {
                    screenSharePub = pub;
                }
            }
        } catch (e) { /* ignore */ }
    }

    return { cameraPub, screenSharePub, screenShareAudioPub };
}

export function useParticipantTrack(participant, source) {
    const [track, setTrack] = useState(null);

    useEffect(() => {
        if (!participant) { setTrack(null); return; }

        const resolve = () => {
            const { cameraPub, screenSharePub } = findTrackPubs(participant);
            const pub = source === 'camera' ? cameraPub : screenSharePub;

            if (pub && !pub.isSubscribed && source === 'camera') {
                pub.setSubscribed(true);
            }

            setTrack(pub?.track || null);
        };

        resolve();
        const interval = setInterval(resolve, 1000);
        const timeout = setTimeout(() => clearInterval(interval), 10000);

        const onPub = () => resolve();
        const onUnpub = () => resolve();

        participant.on(RoomEvent.TrackPublished, onPub);
        participant.on(RoomEvent.TrackUnpublished, onUnpub);
        participant.on(RoomEvent.TrackSubscribed, onPub);
        participant.on(RoomEvent.TrackUnsubscribed, onUnpub);
        participant.on(RoomEvent.TrackMuted, onPub);
        participant.on(RoomEvent.TrackUnmuted, onPub);
        participant.on('localTrackPublished', onPub);
        participant.on('localTrackUnpublished', onUnpub);

        return () => {
            clearInterval(interval);
            clearTimeout(timeout);
            participant.off(RoomEvent.TrackPublished, onPub);
            participant.off(RoomEvent.TrackUnpublished, onUnpub);
            participant.off(RoomEvent.TrackSubscribed, onPub);
            participant.off(RoomEvent.TrackUnsubscribed, onUnpub);
            participant.off(RoomEvent.TrackMuted, onPub);
            participant.off(RoomEvent.TrackUnmuted, onPub);
            participant.off('localTrackPublished', onPub);
            participant.off('localTrackUnpublished', onUnpub);
        };
    }, [participant, source]);

    return track;
}
