// src/components/VideoApp/VideoPlayer.tsx
import React, { useCallback, useContext, useEffect, useRef, useState } from 'react';
import { Box, Typography, Paper, Tooltip, IconButton } from '@mui/material';
import { AccountContext } from 'contexts/AccountContext';
import { axiosInstance } from '../../../../../axiosApi';
import { VideoItem, VideoProgressAPI } from 'types';
import PlayArrowIcon from '@mui/icons-material/PlayArrow';
import PauseIcon from '@mui/icons-material/Pause';
import ReplayIcon from '@mui/icons-material/Replay';
import FullscreenIcon from '@mui/icons-material/Fullscreen';
import ExitFullscreenIcon from '@mui/icons-material/FullscreenExit';

interface VideoProgress {
  id?: number; // Optional as it might not exist for new progress entries
  user?: number; // Assuming user ID is a number
  video?: number; // Video ID
  current_time?: number; // Current playback time in seconds
  completed?: boolean;
  last_watched?: string; // Optional, set by backend
  progress: number;
}

interface VideoPlayerProps {
  video: VideoItem;
  updateVideoItem: (time: number, completed: boolean, progress: number, videoId: number) => void;
}

const VideoPlayer: React.FC<VideoPlayerProps> = ({ video, updateVideoItem }) => {
  const { account, accountLoading } = useContext(AccountContext);

  if (!video || accountLoading) {
    return (
      <Paper
        elevation={2}
        sx={{
          p: 3,
          height: '100%',
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'center',
        }}
      >
        <Typography variant="h6" color="text.secondary">
          No video selected
        </Typography>
      </Paper>
    );
  }

  //
  const videoRef = useRef<HTMLVideoElement>(null);
  const [currentTime, setCurrentTime] = useState(0);
  const [isPlaying, setIsPlaying] = useState(false);
  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [snackbarOpen, setSnackbarOpen] = useState(false);
  const [snackbarMessage, setSnackbarMessage] = useState('');
  const [isFullScreen, setIsFullScreen] = useState(false);
  const debounceTimeoutRef = useRef<NodeJS.Timeout | null>(null);

  // Function to save progress to the backend
  const saveProgress = useCallback(
    async (time: number, completed: boolean = false) => {
      if (!videoRef.current) return;

      const progressData: VideoProgress = {
        progress: Math.round(time),
      };

      try {
        // First, try to fetch existing progress
        const response = await axiosInstance.get(
          `/videos/progress/?user=${account?.id}&video=${video.id}`,
        );
        if (response.data.length > 0) {
          // If progress exists, update it
          const existingProgress = response.data[0];
          await axiosInstance.patch(`/videos/progress/${existingProgress.id}/`, progressData);
          await updateVideoItem(time, completed, progressData.progress, video.id);
        } else {
          // If no progress, create a new one
          await axiosInstance.post('/videos/progress/', progressData);
        }
        if (completed) {
          setSnackbarMessage('Video progress saved: Completed!');
        } else {
          setSnackbarMessage(`Video progress saved: ${Math.floor(time)}s`);
        }
        setSnackbarOpen(true);
      } catch (err) {
        console.error('Failed to save video progress:', err);
        setError('Failed to save video progress.');
      }
    },
    [video.id, account?.id],
  );

  // Fetch initial progress when video changes or component mounts
  useEffect(() => {
    const fetchProgress = async () => {
      setIsLoading(true);
      setError(null);
      try {
        const { data } = await axiosInstance.get<VideoProgressAPI>(
          `/videos/progress/${video.id}/?user=${account?.id}`,
        );

        if (data) {
          const progress: VideoProgress = {
            current_time: data.progress,
            progress: data.progress,
          };
          setCurrentTime(progress?.current_time || 0);

          if (videoRef.current) {
            videoRef.current.currentTime = progress.current_time || 0;
          }
          setSnackbarMessage(`Resuming from ${Math.floor(progress?.current_time || 0)}s`);
          setSnackbarOpen(true);
        } else {
          setCurrentTime(0);
          if (videoRef.current) {
            videoRef.current.currentTime = 0;
          }
        }
      } catch (err) {
        console.error('Failed to fetch video progress:', err);
        setError('Failed to load video progress.');
      } finally {
        setIsLoading(false);
      }
    };

    fetchProgress();

    // Cleanup on unmount or video change
    return () => {
      if (debounceTimeoutRef.current) {
        clearTimeout(debounceTimeoutRef.current);
      }
      // Save final progress when component unmounts or video changes
      if (videoRef.current && !videoRef.current.ended) {
        saveProgress(videoRef.current.currentTime);
      }
    };
  }, [video.id, account?.id, saveProgress]);

  // Video event handlers
  const handleTimeUpdate = () => {
    if (videoRef.current) {
      const newTime = videoRef.current.currentTime;
      setCurrentTime(newTime);

      // Debounce progress saving to avoid too many API calls
      if (debounceTimeoutRef.current) {
        clearTimeout(debounceTimeoutRef.current);
      }
      debounceTimeoutRef.current = setTimeout(() => {
        saveProgress(newTime);
      }, 5000); // Save every 5 seconds of playback
    }
  };

  const handlePlay = () => {
    setIsPlaying(true);
    if (videoRef.current) {
      videoRef.current.play().catch((e) => console.error('Error playing video:', e));
    }
  };

  const handlePause = () => {
    setIsPlaying(false);
    if (videoRef.current) {
      videoRef.current.pause();
      saveProgress(videoRef.current.currentTime); // Save immediately on pause
    }
  };

  const handleEnded = () => {
    setIsPlaying(false);
    saveProgress(video.duration, true); // Mark as completed
  };

  const handleLoadedData = () => {
    setIsLoading(false);
    // Attempt to play if it was playing before, or if it's the first load
    if (videoRef.current && currentTime > 0) {
      videoRef.current.currentTime = currentTime;
      videoRef.current.play().catch((e) => console.error('Error resuming video:', e));
      setIsPlaying(true);
    }
  };

  const handleVideoError = (event: React.SyntheticEvent<HTMLVideoElement, Event>) => {
    console.error('Video error:', event);
    setError('Error loading video. The file might be missing or corrupted.');
    setIsLoading(false);
  };

  const handleReplay = () => {
    if (videoRef.current) {
      videoRef.current.currentTime = 0;
      setCurrentTime(0);
      saveProgress(0, false); // Reset progress
      videoRef.current.play();
      setIsPlaying(true);
    }
  };

  const toggleFullScreen = () => {
    if (!videoRef.current) return;

    if (!document.fullscreenElement) {
      videoRef.current.requestFullscreen().catch((err) => {
        alert(`Error attempting to enable full-screen mode: ${err.message} (${err.name})`);
      });
    } else {
      document.exitFullscreen();
    }
  };

  useEffect(() => {
    const handleFullScreenChange = () => {
      setIsFullScreen(!!document.fullscreenElement);
    };

    document.addEventListener('fullscreenchange', handleFullScreenChange);
    return () => {
      document.removeEventListener('fullscreenchange', handleFullScreenChange);
    };
  }, []);

  const formatTime = (seconds: number) => {
    const minutes = Math.floor(seconds / 60);
    const remainingSeconds = Math.floor(seconds % 60);
    return `${minutes}:${remainingSeconds < 10 ? '0' : ''}${remainingSeconds}`;
  };

  const handleSnackbarClose = (event?: React.SyntheticEvent | Event, reason?: string) => {
    if (reason === 'clickaway') {
      return;
    }
    setSnackbarOpen(false);
  };

  return (
    <Paper elevation={3} sx={{ p: 2 }}>
      <Typography variant="h6" gutterBottom>
        {video.name}
      </Typography>
      <Typography variant="body1" color="text.secondary" sx={{ mb: 2 }}>
        {video.description}
      </Typography>
      <Box
        sx={{ position: 'relative', width: '100%', paddingTop: '56.25%' /* 16:9 Aspect Ratio */ }}
      >
        <video
          ref={videoRef}
          src={video.videoUrl}
          controls={false}
          onTimeUpdate={handleTimeUpdate}
          onEnded={handleEnded}
          onLoadedData={handleLoadedData}
          onError={handleVideoError}
          style={{
            position: 'absolute',
            top: 0,
            left: 0,
            width: '100%',
            height: '100%',
            backgroundColor: '#000',
            borderRadius: 2,
          }}
        >
          <Typography>Your browser does nto support the video tag.</Typography>
        </video>
      </Box>
      <Box sx={{ display: 'flex', alignItems: 'center', mt: 2, justifyContent: 'space-between' }}>
        <Box sx={{ display: 'flex', alignItems: 'center' }}>
          <Tooltip title={isPlaying ? 'Pause' : 'Play'}>
            <IconButton onClick={isPlaying ? handlePause : handlePlay} color="primary" size="large">
              {isPlaying ? <PauseIcon fontSize="inherit" /> : <PlayArrowIcon fontSize="inherit" />}
            </IconButton>
          </Tooltip>
          <Tooltip title="Replay">
            <IconButton onClick={handleReplay} color="primary" size="large">
              <ReplayIcon fontSize="inherit" />
            </IconButton>
          </Tooltip>
          <Typography variant="body2" sx={{ ml: 1 }}>
            {formatTime(currentTime)} / {formatTime(video.duration)}
          </Typography>
        </Box>
        <Tooltip title={isFullScreen ? 'Exit Fullscreen' : 'Fullscreen'}>
          <IconButton onClick={toggleFullScreen} color="primary" size="large">
            {isFullScreen ? (
              <ExitFullscreenIcon fontSize="inherit" />
            ) : (
              <FullscreenIcon fontSize="inherit" />
            )}
          </IconButton>
        </Tooltip>
      </Box>
      <Typography variant="body2" sx={{ mt: 2 }}>
        Current Progress: {Math.round((video.progress / video.duration) * 100)}% - Status:{' '}
        {video.status}
      </Typography>
    </Paper>
  );
};

export default VideoPlayer;
