import { ReactEventHandler, Ref, RefObject, useCallback, useEffect, useMemo, useRef, useState } from "react";
import { QortalGetMetadata } from "../../types/interfaces/resources";
import { VideoContainer, VideoElement } from "./VideoPlayer-styles";
import { useVideoPlayerHotKeys } from "./useVideoPlayerHotKeys";
import { useProgressStore, useVideoStore } from "../../state/video";
import { useVideoPlayerController } from "./useVideoPlayerController";
import { LoadingVideo } from "./LoadingVideo";
import { VideoControlsBar } from "./VideoControlsBar";
import videojs from 'video.js';
import 'video.js/dist/video-js.css';

import Player from "video.js/dist/types/player";
import { Subtitle, SubtitleManager, SubtitlePublishedData } from "./SubtitleManager";
import { base64ToBlobUrl } from "../../utils/base64";
import convert from 'srt-webvtt';

export async function srtBase64ToVttBlobUrl(base64Srt: string): Promise<string | null> {
  try {
    // Step 1: Convert base64 string to a Uint8Array
    const binary = atob(base64Srt);
    const bytes = new Uint8Array(binary.length);
    for (let i = 0; i < binary.length; i++) {
      bytes[i] = binary.charCodeAt(i);
    }

    // Step 2: Create a Blob from the Uint8Array with correct MIME type
    const srtBlob = new Blob([bytes], { type: 'application/x-subrip' });
    console.log('srtBlob', srtBlob)
    // Step 3: Use convert() with the Blob
    const vttBlobUrl: string = await convert(srtBlob);
    return vttBlobUrl
  } catch (error) {
    console.error('Failed to convert SRT to VTT:', error);
    return null;
  }
}
type StretchVideoType = "contain" | "fill" | "cover" | "none" | "scale-down";


 interface VideoPlayerProps {
  qortalVideoResource: QortalGetMetadata;
  videoRef: Ref<HTMLVideoElement>;
  retryAttempts?: number;
  poster?: string;
  autoPlay?: boolean;
  onEnded?: (e: React.SyntheticEvent<HTMLVideoElement, Event>) => void;
}

const videoStyles = {
  videoContainer: { },
  video: { },
};

async function loadMediaInfo(wasmPath = '/MediaInfoModule.wasm') {
  const mediaInfoModule = await import('mediainfo.js');
  return await mediaInfoModule.default({
    format: 'JSON',
    full: true,
    locateFile: () => wasmPath,
  });
}

async function getVideoMimeTypeFromUrl(qortalVideoResource: any): Promise<string | null> {

  try {
    const metadataResponse = await fetch(`/arbitrary/metadata/${qortalVideoResource.service}/${qortalVideoResource.name}/${qortalVideoResource.identifier}`)
  const metadataData = await metadataResponse.json()
  return metadataData?.mimeType || null
  } catch (error) {
    return null
  }
  // const mediaInfo = await loadMediaInfo();
  // const chunkCache = new Map<string, Uint8Array>();

  // let fileSize = 0;
  // try {
  //   const headResp = await fetch(videoUrl, { method: 'HEAD' });
  //   const lengthHeader = headResp.headers.get('Content-Length');
  //   if (!lengthHeader) throw new Error('Missing content length');
  //   fileSize = parseInt(lengthHeader, 10);
  // } catch (err) {
  //   console.error('Error fetching content length:', err);
  //   return null;
  // }

  // try {
  //   const rawResult = await mediaInfo.analyzeData(
  //     () => fileSize,
  //     async (chunkSize: number, offset: number): Promise<Uint8Array> => {
  //       const key = `${offset}:${chunkSize}`;
  //       if (chunkCache.has(key)) return chunkCache.get(key)!;

  //       const end = Math.min(fileSize - 1, offset + chunkSize - 1);
  //       const resp = await fetch(videoUrl, {
  //         headers: { Range: `bytes=${offset}-${end}` },
  //       });

  //       if (!resp.ok || (resp.status !== 206 && fileSize > chunkSize)) {
  //         console.warn(`Range request failed: ${resp.status}`);
  //         return new Uint8Array();
  //       }

  //       const blob = await resp.blob();
  //       const buffer = new Uint8Array(await blob.arrayBuffer());
  //       chunkCache.set(key, buffer);
  //       return buffer;
  //     }
  //   );

  //   const result = JSON.parse(rawResult);
  //   const tracks = result?.media?.track;

  //   const videoTrack = tracks?.find((t: any) => t['@type'] === 'Video');
  //   const format = videoTrack?.Format?.toLowerCase();

  //   switch (format) {
  //     case 'avc':
  //     case 'h264':
  //     case 'mpeg-4':
  //     case 'mp4':
  //       return 'video/mp4';
  //     case 'vp8':
  //     case 'vp9':
  //       return 'video/webm';
  //     case 'hevc':
  //     case 'h265':
  //       return 'video/mp4'; // still usually wrapped in MP4
  //     case 'matroska':
  //       return 'video/webm';
  //     default:
  //       return 'video/mp4'; // fallback
  //   }
  // } catch (err) {
  //   console.error('Error analyzing media info:', err);
  //   return null;
  // }
}

export const VideoPlayer = ({
  videoRef,
  qortalVideoResource,
  retryAttempts,
  poster,
  autoPlay,
  onEnded,
}: VideoPlayerProps) => {
  const containerRef = useRef<RefObject<HTMLDivElement> | null>(null);
  const [videoObjectFit] = useState<StretchVideoType>("contain");
  const [isPlaying, setIsPlaying] = useState(false);
  const { volume, setVolume, setPlaybackRate, playbackRate } = useVideoStore((state) => ({
    volume: state.playbackSettings.volume,
    setVolume: state.setVolume,
    setPlaybackRate: state.setPlaybackRate,
    playbackRate: state.playbackSettings.playbackRate
  }));
  const playerRef = useRef<Player | null>(null);
  const [isPlayerInitialized, setIsPlayerInitialized] = useState(false)
  const [videoCodec, setVideoCodec] = useState<null | false | string>(null)
  const [isMuted, setIsMuted] = useState(false);
  const { setProgress } = useProgressStore();
  const [localProgress, setLocalProgress] = useState(0)
  const [duration, setDuration] = useState(0)
  const [isLoading, setIsLoading] = useState(true);
  const [showControls, setShowControls] = useState(false)
  const [isOpenSubtitleManage, setIsOpenSubtitleManage] = useState(false)
  const subtitleBtnRef = useRef(null)
  const {
    reloadVideo,
    togglePlay,
    onVolumeChange,
    increaseSpeed,
    decreaseSpeed,
    toggleMute,
    isFullscreen,
    toggleObjectFit,
    controlsHeight,
    setProgressRelative,
    toggleAlwaysShowControls,
    changeVolume,
    startedFetch,
    isReady,
    resourceUrl,
    startPlay,
    setProgressAbsolute,
    setAlwaysShowControls,
    status, percentLoaded,
    showControlsFullScreen,
    
  } = useVideoPlayerController({
    autoPlay,
    playerRef,
    qortalVideoResource,
    retryAttempts,
    isPlayerInitialized
  });

  const hotkeyHandlers = useMemo(
    () => ({
      reloadVideo,
      togglePlay,
      setProgressRelative,
      toggleObjectFit,
      toggleAlwaysShowControls,
      increaseSpeed,
      decreaseSpeed,
      changeVolume,
      toggleMute,
      setProgressAbsolute,
      setAlwaysShowControls,
    }),
    [
      reloadVideo,
      togglePlay,
      setProgressRelative,
      toggleObjectFit,
      toggleAlwaysShowControls,
      increaseSpeed,
      decreaseSpeed,
      changeVolume,
      toggleMute,
      setProgressAbsolute,
      setAlwaysShowControls,
    ]
  );





const closeSubtitleManager = useCallback(()=> {
  setIsOpenSubtitleManage(false)
}, [])
  const openSubtitleManager = useCallback(()=> {
  setIsOpenSubtitleManage(true)
}, [])

  const videoLocation = useMemo(() => {
    if (!qortalVideoResource) return null;
    return `${qortalVideoResource.service}-${qortalVideoResource.name}-${qortalVideoResource.identifier}`;
  }, [qortalVideoResource]);
  useVideoPlayerHotKeys(hotkeyHandlers);

  const updateProgress = useCallback(() => {
  const player = playerRef?.current;
  if (!player || typeof player?.currentTime !== 'function') return;

  const currentTime = player.currentTime();
  if (typeof currentTime === 'number' && videoLocation && currentTime > 0.1) {
    setProgress(videoLocation, currentTime);
    setLocalProgress(currentTime);
  }
}, [videoLocation]);
  // useEffect(() => {
  //   const ref = videoRef as React.RefObject<HTMLVideoElement>;
  //   if (!ref.current) return;
  //   if (ref.current) {
  //     ref.current.volume = volume;
  //   }
  //   // Only run on mount
  //   // eslint-disable-next-line react-hooks/exhaustive-deps
  // }, []);

  const onPlay = useCallback(() => {
    setIsPlaying(true);
  }, [setIsPlaying]);

  const onPause = useCallback(() => {
    setIsPlaying(false);
  }, [setIsPlaying]);
  const onVolumeChangeHandler = useCallback(
    (e: React.SyntheticEvent<HTMLVideoElement, Event>) => {
      try {
        const video = e.currentTarget;
      setVolume(video.volume);
      setIsMuted(video.muted);
      } catch (error) {
        console.error('onVolumeChangeHandler', onVolumeChangeHandler)
      }
    },
    [setIsMuted, setVolume]
  );



  const videoStylesContainer = useMemo(() => {
    return {
      cursor: showControls ? 'auto' : 'none',
      aspectRatio: '16 / 9',
      ...videoStyles?.videoContainer,
    };
  }, [showControls]);


  const videoStylesVideo = useMemo(() => {
    return {
      ...videoStyles?.video,
      objectFit: videoObjectFit,
      backgroundColor: "#000000",
      height: isFullscreen  ? "calc(100vh - 40px)" : "100%",
      width: '100%'
    };
  }, [videoObjectFit, isFullscreen]);

  const handleEnded = useCallback(
    (e: React.SyntheticEvent<HTMLVideoElement, Event>) => {
      if (onEnded) {
        onEnded(e);
      }
    },
    [onEnded]
  );

  const handleCanPlay = useCallback(()=> {
    setIsLoading(false);
  }, [setIsLoading])

 useEffect(() => {
  if(!isPlayerInitialized) return
  const player = playerRef.current;
  if (!player || typeof player.on !== 'function') return;

  const handleLoadedMetadata = () => {
    const duration = player.duration?.();
    if (typeof duration === 'number' && !isNaN(duration)) {
      setDuration(duration);
    }
  };

  player.on('loadedmetadata', handleLoadedMetadata);

  return () => {
    player.off('loadedmetadata', handleLoadedMetadata);
  };
}, [isPlayerInitialized]);


  const enterFullscreen = () => {
    const ref = containerRef?.current as any;
    if (!ref) return;

    if (ref.requestFullscreen && !isFullscreen) {
      ref.requestFullscreen();
    }


  };

  const exitFullscreen = () => {
    if (isFullscreen) document.exitFullscreen();
  };

  const toggleFullscreen = () => {
    isFullscreen ? exitFullscreen() : enterFullscreen();
  };

const canvasRef = useRef(null)
const videoRefForCanvas = useRef<any>(null)
const extractFrames = useCallback( (time: number): void => {
  // const video = videoRefForCanvas?.current;
  // const canvas: any = canvasRef.current;

  // if (!video || !canvas) return null;

  // // Avoid unnecessary resize if already correct
  // if (canvas.width !== video.videoWidth || canvas.height !== video.videoHeight) {
  //   canvas.width = video.videoWidth;
  //   canvas.height = video.videoHeight;
  // }

  // const context = canvas.getContext("2d");
  // if (!context) return null;

  // // If video is already near the correct time, don't seek again
  // const threshold = 0.01; // 10ms threshold
  // if (Math.abs(video.currentTime - time) > threshold) {
  //   await new Promise<void>((resolve) => {
  //     const onSeeked = () => resolve();
  //     video.addEventListener("seeked", onSeeked, { once: true });
  //     video.currentTime = time;
  //   });
  // }

  // context.drawImage(video, 0, 0, canvas.width, canvas.height);

  // // Use a faster method for image export (optional tradeoff)
  // const blob = await new Promise<Blob | null>((resolve) => {
  //   canvas.toBlob((blob: any) => resolve(blob), "image/webp", 0.7);
  // });

  // if (!blob) return null;

  // return URL.createObjectURL(blob);
}, []);


  const hideTimeout = useRef<any>(null);
   

const resetHideTimer = () => {
  setShowControls(true);
  if (hideTimeout.current) clearTimeout(hideTimeout.current);
  hideTimeout.current = setTimeout(() => {
    setShowControls(false);
  }, 2500); // 3s of inactivity
};

const handleMouseMove = () => {
  resetHideTimer();
};

useEffect(() => {
  resetHideTimer(); // initial show
  return () => {
    if (hideTimeout.current) clearTimeout(hideTimeout.current);
  };
}, []);

const previousSubtitleUrlRef = useRef<string | null>(null);

useEffect(() => {
  return () => {
    // Component unmount cleanup
    if (previousSubtitleUrlRef.current) {
      URL.revokeObjectURL(previousSubtitleUrlRef.current);
      previousSubtitleUrlRef.current = null;
    }
  };
}, []);

const onSelectSubtitle = useCallback(async (subtitle: SubtitlePublishedData)=> {
  console.log('onSelectSubtitle', subtitle)
  const player = playerRef.current;
  if (!player || !subtitle.subtitleData || !subtitle.type) return;

  // Cleanup: revoke previous Blob URL
  if (previousSubtitleUrlRef.current) {
    URL.revokeObjectURL(previousSubtitleUrlRef.current);
    previousSubtitleUrlRef.current = null;
  }
  let blobUrl
  if(subtitle?.type === "application/x-subrip"){
    blobUrl = await srtBase64ToVttBlobUrl(subtitle.subtitleData)
  } else {
   blobUrl =  base64ToBlobUrl(subtitle.subtitleData, subtitle.type)

  }
  
  previousSubtitleUrlRef.current = blobUrl;

const remoteTracksList = playerRef.current?.remoteTextTracks();

if (remoteTracksList) {
  const toRemove: TextTrack[] = [];

  // Bypass TS restrictions safely
  const list = remoteTracksList as unknown as { length: number; [index: number]: TextTrack };

  for (let i = 0; i < list.length; i++) {
    const track = list[i];
    if (track) toRemove.push(track);
  }

  toRemove.forEach((track) => {
    playerRef.current?.removeRemoteTextTrack(track);
  });
}
     playerRef.current?.addRemoteTextTrack({
    kind: 'subtitles',
    src: blobUrl,
    srclang: 'en',
    label: 'English',
    default: true
  }, true); 

   // Remove all existing remote text tracks
//  try {
//    const remoteTracks = playerRef.current?.remoteTextTracks()?.tracks_
//   if (remoteTracks && remoteTracks?.length) {
//     const toRemove: TextTrack[] = [];
//     for (let i = 0; i < remoteTracks.length; i++) {
//       const track = remoteTracks[i];
//       toRemove.push(track);
//     }
//     toRemove.forEach((track) => {
//       console.log('removing track')
//       playerRef.current?.removeRemoteTextTrack(track);
//     });
//   }
//  } catch (error) {
//   console.log('error2', error)
//  }

await new Promise((res)=> {
  setTimeout(() => {
    res(null)
  }, 1000);
})
const tracksInfo = playerRef.current?.textTracks();
console.log('tracksInfo', tracksInfo)
if (!tracksInfo) return;

const tracks = Array.from({ length: (tracksInfo as any).length }, (_, i) => (tracksInfo as any)[i]);
console.log('tracks', tracks)
for (const track of tracks) {
  console.log('track', track)

  if (track.kind === 'subtitles') {
    track.mode = 'showing'; // force display
  }
}


},[])

  const handleMouseLeave = useCallback(() => {
    setShowControls(false);
    if (hideTimeout.current) clearTimeout(hideTimeout.current);
  }, [setShowControls]);


  const videoLocactionStringified = useMemo(()=> {
    return JSON.stringify(qortalVideoResource)
  }, [qortalVideoResource])

useEffect(() => {
  if (!resourceUrl || !isReady || !videoLocactionStringified || !startPlay) return;

  const resource = JSON.parse(videoLocactionStringified)
  let canceled = false;

 try {
   const setupPlayer = async () => {
    const type = await getVideoMimeTypeFromUrl(resource);
    if (canceled) return;

    const options = {
      autoplay: true,
      controls: false,
      responsive: true,
      fluid: true,
      poster: startPlay ? "" : poster,
      aspectRatio: '16:9' ,
      sources: [
        {
          src: resourceUrl,
          type: type || 'video/mp4', // fallback
        },
      ],
    };
    const ref = videoRef as any;
    if (!ref.current) return;

    if (!playerRef.current && ref.current) {
      playerRef.current = videojs(ref.current, options, () => {
        setIsPlayerInitialized(true)
        playerRef.current?.poster('');
        playerRef.current?.playbackRate(playbackRate)
        playerRef.current?.volume(volume);
        
 
        playerRef.current?.play();
    
      });
            playerRef.current?.on('error', () => {
    const error = playerRef.current?.error();
    console.error('Video.js playback error:', error);
    // Optional: display user-friendly message
  });
    }
  };

  setupPlayer();

 } catch (error) {
  console.error('useEffect start player', error)
 }
 return () => {
  canceled = true;
  const player = playerRef.current;

  if (player && typeof player.dispose === 'function') {
    try {
      player.dispose();
    } catch (err) {
      console.error('Error disposing Video.js player:', err);
    }
    playerRef.current = null;
  }
};
}, [isReady, resourceUrl, startPlay, poster, videoLocactionStringified]);

  useEffect(() => {
    if(!isPlayerInitialized) return
  const player = playerRef?.current;
  if (!player) return;

  const handleRateChange = () => {
    const newRate = player?.playbackRate();
    if(newRate){
      setPlaybackRate(newRate); // or any other state/action
    }
  };

  player.on('ratechange', handleRateChange);

  return () => {
    player.off('ratechange', handleRateChange);
  };
}, [isPlayerInitialized]);

  return (
    <>
     {/* <video controls  src={"http://127.0.0.1:22393/arbitrary/VIDEO/a-test/MYTEST2_like_MYTEST2_vid_test-parallel_cSYmIk"} ref={videoRefForCanvas} ></video> */}
   
    <VideoContainer
      tabIndex={0}
      style={videoStylesContainer}
      onMouseMove={handleMouseMove}
      onMouseLeave={handleMouseLeave}
      ref={containerRef}
    >
      <LoadingVideo togglePlay={togglePlay} isReady={isReady} status={status} percentLoaded={percentLoaded} isLoading={isLoading} />
      <VideoElement
        ref={videoRef}
        tabIndex={0}
          className="video-js"

        src={isReady && startPlay ? resourceUrl || undefined : undefined}
        poster={startPlay ? "" : poster}
        onTimeUpdate={updateProgress}
        autoPlay={autoPlay}
        onClick={togglePlay}
        onEnded={handleEnded}
        onCanPlay={handleCanPlay}
        preload="metadata"
        style={videoStylesVideo}
        onPlay={onPlay}
        onPause={onPause}
        onVolumeChange={onVolumeChangeHandler}
        controls={false}
    
      />
            {/* <canvas ref={canvasRef} style={{ display: "none" }}></canvas> */}
           
          
        {isReady && (
             <VideoControlsBar subtitleBtnRef={subtitleBtnRef}  playbackRate={playbackRate}   increaseSpeed={hotkeyHandlers.increaseSpeed}
      decreaseSpeed={hotkeyHandlers.decreaseSpeed} playerRef={playerRef} isFullScreen={isFullscreen} showControlsFullScreen={showControlsFullScreen} showControls={showControls} extractFrames={extractFrames} toggleFullscreen={toggleFullscreen} onVolumeChange={onVolumeChange} volume={volume}  togglePlay={togglePlay} reloadVideo={hotkeyHandlers.reloadVideo} isPlaying={isPlaying} canPlay={true} isScreenSmall={false} controlsHeight={controlsHeight}  duration={duration} progress={localProgress} openSubtitleManager={openSubtitleManager} />
        )}       
  
          <SubtitleManager subtitleBtnRef={subtitleBtnRef} close={closeSubtitleManager} open={isOpenSubtitleManage} qortalMetadata={qortalVideoResource} onSelect={onSelectSubtitle} />
    </VideoContainer>
     </>
  );
};