import React, { useCallback, useMemo, useRef, useEffect } from 'react';

import ReactPlayer from 'react-player';

import handle from '@enact/core/handle';

var handledMediaEventsMap = [
  'onReady',
  'onStart',
  'onPlay',
  'onProgress',
  'onDuration',
  'onPause',
  'onBuffer',
  'onBufferEnd',
  'onSeek',
  'onEnded',
  'onError',
];

export default function TReactPlayer({
  mediaEventsMap = handledMediaEventsMap,
  videoRef,
  url,
  dispatch,
  ...rest
}) {
  const playerRef = useRef(null);

  // 🔽 [최적화] handleEvent의 주요 의존성 추출
  const playing = rest?.playing;
  const config = rest?.config;

  const handleEvent = useCallback(
    (type) => (ev) => {
      if (type === 'onReady') {
        if (videoRef) {
          const videoNode = playerRef.current.getInternalPlayer();
          videoRef(videoNode);
          const iframeEl =
            typeof playerRef.current?.getInternalPlayer === 'function'
              ? playerRef.current.getInternalPlayer('iframe')
              : null;
          if (iframeEl) {
            iframeEl.setAttribute('tabIndex', '-1');
            iframeEl.setAttribute('aria-hidden', 'true');
          }
          if (
            videoNode.tagName &&
            !Object.prototype.hasOwnProperty.call(videoNode, 'proportionPlayed')
          ) {
            Object.defineProperties(videoNode, {
              error: {
                get: function () {
                  return videoNode.networkState === videoNode.NETWORK_NO_SOURCE;
                },
              },
              loading: {
                get: function () {
                  return videoNode.readyState < videoNode.HAVE_ENOUGH_DATA;
                },
              },
              proportionLoaded: {
                get: function () {
                  return (
                    videoNode.buffered.length &&
                    videoNode.buffered.end(videoNode.buffered.length - 1) / videoNode.duration
                  );
                },
              },
              proportionPlayed: {
                get: function () {
                  return videoNode.currentTime / videoNode.duration;
                },
              },
            });
          } else if (!Object.prototype.hasOwnProperty.call(videoNode, 'proportionPlayed')) {
            videoNode.play = videoNode.playVideo;
            videoNode.pause = videoNode.pauseVideo;
            videoNode.seek = videoNode.seekTo;
            Object.defineProperties(videoNode, {
              currentTime: {
                get: function () {
                  return videoNode.getCurrentTime();
                },
                set: function (time) {
                  videoNode.seekTo(time);
                },
              },
              duration: {
                get: function () {
                  return videoNode.getDuration();
                },
              },
              paused: {
                get: function () {
                  return videoNode.getPlayerState() !== 1;
                },
              },
              error: {
                get: function () {
                  return !!videoNode?.playerInfo?.videoData?.errorCode;
                },
              },
              loading: {
                get: function () {
                  return !videoNode?.playerInfo?.videoData?.isPlayable; //todo
                },
              },
              proportionLoaded: {
                get: function () {
                  return videoNode?.getVideoBytesLoaded() ?? 0;
                },
              },
              proportionPlayed: {
                get: function () {
                  const duration = videoNode.getDuration();
                  return duration ? videoNode.getCurrentTime() / duration : 0;
                },
              },
              playbackRate: {
                get: function () {
                  return videoNode?.playerInfo?.playbackRate;
                },
                set: function (playbackRate) {
                  if (videoNode && videoNode.setPlaybackRate) {
                    videoNode.setPlaybackRate(playbackRate);
                  }
                },
              },
            });
          }
        }
        handle.forward('onLoadStart', { type, ev }, rest);
      }
      if (type === 'onEnded' && rest?.isYoutube && rest?.type === 'VOD') {
        // YouTube 재생 종료 시 iframe이 포커스를 가져가는 문제를 방지
        const iframeEl =
          typeof playerRef.current?.getInternalPlayer === 'function'
            ? playerRef.current.getInternalPlayer('iframe')
            : null;
        iframeEl?.blur();
      }
      handle.forward('onUpdate', { type, ev }, rest);
    },
    [videoRef, playing, config] // ✅ 주요 의존성 추가
  );

  const handledMediaEvents = useMemo(() => {
    const events = {};
    for (let i = 0; i < mediaEventsMap.length; i++) {
      const eventName = mediaEventsMap[i];
      events[eventName] = handleEvent(eventName);
    }
    return events;
  }, [handleEvent, mediaEventsMap]);

  // 🔽 [최적화] URL 변경 또는 언마운트 시 이전 비디오 정리 (메모리 누수 방지)
  useEffect(() => {
    return () => {
      const videoNode = playerRef.current?.getInternalPlayer();
      if (videoNode && videoNode.pause) {
        console.log('[VIDEO-DEBUG] 🧹 비디오 정리 (URL 변경 또는 언마운트)');
        videoNode.pause();
        videoNode.src = '';
        videoNode.srcObject = null;
      }
    };
  }, [url]); // ✅ URL 변경 시에도 정리 로직 실행

  return (
    <ReactPlayer
      ref={playerRef}
      url={url}
      progressInterval={1000}
      config={rest.config}
      {...handledMediaEvents}
      {...rest}
      playsinline // Add playsinline attribute here
    />
  );
}
