import {
  type Dispatch,
  forwardRef,
  type SetStateAction,
  useEffect,
} from 'react';

import { IconPlayerPlay } from '@material-hu/icons/tabler';
import Box from '@material-hu/mui/Box';
import CircularProgress from '@material-hu/mui/CircularProgress';
import { useTheme } from '@material-hu/mui/index';
import { type SxProps } from '@material-hu/mui/styles';

import HuAvatar, {
  type AvatarProps,
} from '@material-hu/components/design-system/Avatar';

import fallbackImage from 'src/assets/images/gray-backgound.webp';
import { useIntersectionObserver } from 'src/hooks/useIntersectionObserver';
import { type AttachmentLoadError } from 'src/pages/dashboard/Conversations/types';

import { useGetCorrectAttachmentUrl } from '../../hooks/useConversationsQueries';
import useGeneratePosterVideos from '../../hooks/useGeneratePosterVideos';

type LazySecureVideoProps = {
  conversationId?: string;
  url?: string;
  thumbnailUrl?: string;
  sx?: SxProps;
  hasControls?: boolean;
  onLoadedMetadata?: (e?: React.SyntheticEvent<HTMLVideoElement>) => void;
  hasPlayerButton?: boolean;
  onCanPlay?: () => void;
  onLoadStart?: () => void;
  avatarSize?: AvatarProps['size'];
  canSeeVideo?: boolean;
  onUpdateAttachmentLoadError?: Dispatch<SetStateAction<AttachmentLoadError>>;
};

const LazySecureVideo = forwardRef<HTMLVideoElement, LazySecureVideoProps>(
  (props, ref) => {
    const {
      conversationId,
      url = '',
      thumbnailUrl,
      sx,
      hasControls = false,
      onLoadedMetadata,
      hasPlayerButton = true,
      onCanPlay,
      onLoadStart,
      avatarSize,
      canSeeVideo = false,
      onUpdateAttachmentLoadError,
    } = props;
    const theme = useTheme();
    const { targetRef, hasBeenVisible } = useIntersectionObserver();

    const shouldLoad = canSeeVideo || hasBeenVisible;

    const {
      data: correctVideoUrl,
      isLoading,
      isError: isErrorCorrectVideoUrl,
      refetch: refetchCorrectVideoUrl,
    } = useGetCorrectAttachmentUrl({
      url,
      conversationId,
      enabledToShowError: false,
      enabled: !!url && shouldLoad,
      onError: () => {
        onUpdateAttachmentLoadError?.(prev => [
          ...(prev ?? []),
          {
            url,
            isError: true,
            retry: () => {
              refetchCorrectVideoUrl();
            },
          },
        ]);
      },
      onSuccess: () => {
        onUpdateAttachmentLoadError?.(prev =>
          (prev ?? []).filter(error => error.url !== url),
        );
      },
    });

    const getThumbnailPosterLoadHandlers = () => ({
      onError: () => {
        onUpdateAttachmentLoadError?.(prev => [
          ...(prev ?? []),
          {
            url: thumbnailUrl,
            isError: true,
            retry: () => {
              refetchThumbUrl();
              refetchGeneratedPoster();
            },
          },
        ]);
      },
      onSuccess: () => {
        onUpdateAttachmentLoadError?.(prev =>
          (prev ?? []).filter(error => error.url !== thumbnailUrl),
        );
        onUpdateAttachmentLoadError?.(prev =>
          (prev ?? []).filter(error => error.url !== correctVideoUrl),
        );
      },
    });

    const {
      data: thumbUrl,
      isLoading: isLoadingThumbUrl,
      isError: isErrorThumbUrl,
      refetch: refetchThumbUrl,
    } = useGetCorrectAttachmentUrl({
      url: thumbnailUrl || '',
      enabledToShowError: false,
      enabled: !!thumbnailUrl && shouldLoad,
      ...getThumbnailPosterLoadHandlers(),
    });

    const {
      generatedPoster,
      isGeneratingPoster,
      isError: isErrorGeneratedPoster,
      refetch: refetchGeneratedPoster,
    } = useGeneratePosterVideos({
      correctVideoUrl: correctVideoUrl || '',
      thumbnailUrl,
      ...getThumbnailPosterLoadHandlers(),
    });

    if (isErrorCorrectVideoUrl || isErrorThumbUrl || isErrorGeneratedPoster) {
      return (
        <IconPlayerPlay
          size={24}
          color={theme.palette.new.text.neutral.brand}
        />
      );
    }

    if (isLoading || isLoadingThumbUrl || isGeneratingPoster) {
      return (
        <Box
          ref={targetRef}
          sx={{
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'center',
            ...sx,
          }}
        >
          <CircularProgress size={24} />
        </Box>
      );
    }

    return (
      <Box
        sx={sx}
        ref={targetRef}
      >
        {hasPlayerButton && !isLoading && !isLoadingThumbUrl && (
          <Box
            sx={{
              position: 'absolute',
              top: 0,
              left: 0,
              width: '100%',
              height: '100%',
              display: 'flex',
              alignItems: 'center',
              justifyContent: 'center',
              zIndex: 1,
            }}
          >
            <HuAvatar
              Icon={IconPlayerPlay}
              size={avatarSize}
            />
          </Box>
        )}
        <>
          {!canSeeVideo && hasBeenVisible && (
            <Box
              component="img"
              loading="lazy"
              src={thumbUrl || generatedPoster || fallbackImage}
              alt=""
              sx={{ width: '100%', height: '100%', objectFit: 'cover' }}
            />
          )}
        </>
        <>
          {canSeeVideo && correctVideoUrl && !isLoading && (
            <video
              ref={ref}
              src={correctVideoUrl}
              onLoadedMetadata={onLoadedMetadata}
              onLoadStart={onLoadStart}
              onCanPlay={onCanPlay}
              preload="none"
              controls={hasControls}
            />
          )}
        </>
      </Box>
    );
  },
);

LazySecureVideo.displayName = 'LazySecureVideo';

export default LazySecureVideo;
