import { type FC, useEffect, useRef, useState } from 'react';

import { IconPlayerPause, IconPlayerPlay } from '@material-hu/icons/tabler';
import Box from '@material-hu/mui/Box';
import CircularProgress from '@material-hu/mui/CircularProgress';
import Stack from '@material-hu/mui/Stack';

import HuAvatar from '@material-hu/components/design-system/Avatar';

import {
  getVideoElapsedTime,
  getVideoRemainingTime,
} from 'src/utils/attachments';

import LazySecureAwareVideo, {
  type LazySecureAwareVideoProps,
} from '../../shared/LazySecureAwareVideo';

import PlayerVideoController from './PlayerVideoController';

export type VideoProps = LazySecureAwareVideoProps & {
  controlsVisible?: boolean;
};

const HIDE_CONTROLS_TIMEOUT = 2000;

const PlayerVideo: FC<VideoProps> = ({ controlsVisible, ...props }) => {
  const { url, conversationId, sxDefault } = props;
  const { height, width } = (sxDefault ?? {}) as {
    height?: number;
    width?: number;
  };
  const videoRef = useRef<HTMLVideoElement>(null);
  const hideTimeoutRef = useRef<NodeJS.Timeout | null>(null);
  const [playedTime, setPlayedTime] = useState<number | number[]>(0);
  const [canPlay, setCanPlay] = useState(false);
  const [showControls, setShowControls] = useState(true);
  const [totalDuration, setTotalDuration] = useState<number>(0);

  useEffect(() => {
    const handleTimeUpdate = (e: Event) => {
      const video = e.currentTarget as HTMLVideoElement;
      if (!Number.isNaN(video.duration) && video.duration > 0) {
        setPlayedTime((video.currentTime * 100) / video.duration);
      }
    };

    const video = videoRef.current;
    if (video) {
      video.load();
      video.addEventListener('timeupdate', handleTimeUpdate);
    }

    return () => {
      video?.removeEventListener('timeupdate', handleTimeUpdate);
      setPlayedTime(0);
      setShowControls(true);
      setCanPlay(false);

      if (hideTimeoutRef.current) {
        clearTimeout(hideTimeoutRef.current);
      }
    };
  }, [url]);

  const handleLoadedMetadata = () => {
    if (videoRef.current) {
      setTotalDuration(Math.floor(videoRef.current.duration));
      // necesary only for blob
      handleCanPlay();
    }
  };

  const handleSeekChange = (_event: Event, value: number | number[]) => {
    if (!videoRef.current || Array.isArray(value)) return;

    setPlayedTime(value);
    videoRef.current.currentTime = (value * totalDuration) / 100;
  };

  const elapsedTime = getVideoElapsedTime(videoRef?.current, totalDuration);

  const remainingTime = getVideoRemainingTime(videoRef?.current);

  const handleMouseMove = () => {
    if (!canPlay) return;
    setShowControls(true);

    if (hideTimeoutRef.current) {
      clearTimeout(hideTimeoutRef.current);
    }

    hideTimeoutRef.current = setTimeout(() => {
      setShowControls(false);
    }, HIDE_CONTROLS_TIMEOUT);
  };

  const handleOnClick = () => {
    if (!canPlay || !videoRef.current) return;

    const { paused } = videoRef.current;

    paused ? videoRef.current.play() : videoRef.current.pause();

    setShowControls(true);
    if (hideTimeoutRef.current) clearTimeout(hideTimeoutRef.current);

    if (!paused) {
      hideTimeoutRef.current = setTimeout(() => {
        setShowControls(false);
      }, HIDE_CONTROLS_TIMEOUT);
    } else {
      setShowControls(false);
    }
  };

  const handleCanPlay = () => setCanPlay(true);

  const getCorrectIcon = (videoCurrent: HTMLVideoElement | null) => {
    if (!canPlay) {
      return <CircularProgress size={24} />;
    }
    if (!videoCurrent || !videoCurrent?.paused) {
      return <HuAvatar Icon={IconPlayerPause} />;
    }
    return <HuAvatar Icon={IconPlayerPlay} />;
  };

  return (
    <Stack
      sx={{
        position: 'relative',
        mx: 'auto',
        width,
        maxWidth: '100%',
        justifyContent: 'center',
        alignItems: 'center',
        borderRadius: 1,
      }}
    >
      <Stack
        sx={{
          alignItems: 'center',
          justifyContent: 'center',
          position: 'relative',
          cursor: canPlay ? 'pointer' : 'default',
          height,
          width,
          borderRadius: 1,
        }}
        onMouseMove={handleMouseMove}
        onClick={handleOnClick}
      >
        <LazySecureAwareVideo
          conversationId={conversationId}
          ref={videoRef}
          hasPlayerButton={false}
          onLoadedMetadata={handleLoadedMetadata}
          onCanPlay={handleCanPlay}
          canSeeVideo
          {...props}
        />
        {showControls && (
          <Box
            sx={{
              position: 'absolute',
              top: 0,
              left: 0,
              width: '100%',
              height: '100%',
              display: 'flex',
              alignItems: 'center',
              justifyContent: 'center',
            }}
          >
            {getCorrectIcon(videoRef?.current)}
          </Box>
        )}

        {canPlay && (
          <PlayerVideoController
            remainingTime={remainingTime}
            playedTime={playedTime}
            handleSeekChange={handleSeekChange}
            elapsedTime={elapsedTime}
            totalDuration={totalDuration}
            visible={controlsVisible ?? showControls}
          />
        )}
      </Stack>
    </Stack>
  );
};

PlayerVideo.displayName = 'PlayerVideo';

export default PlayerVideo;
