import type React from 'react';
import { type FC, type PropsWithChildren } from 'react';

import { useDimensions } from '@material-hu/hooks/useDimensions';
import Stack from '@material-hu/mui/Stack';
import { type SxProps } from '@material-hu/mui/styles';

import {
  type AttachmentLoadError,
  type SendFileItem,
  type SendVideosType,
} from 'src/pages/dashboard/Conversations/types';
import {
  getScaledDimensions,
  isImageAttachment,
  isVideoAttachment,
} from 'src/pages/dashboard/Conversations/utils';

import useZoomPan from '../../../hooks/useZoomPan';
import PlayerVideo from '../../ConversationsThread/ConversationMessage/PlayerVideo';
import LazySecureAwareImage from '../LazySecureAwareImage';

const MediaWrapper: FC<PropsWithChildren> = ({ children }) => (
  <Stack
    sx={{
      width: '100%',
      height: '100%',
      alignItems: 'center',
      justifyContent: 'center',
    }}
  >
    {children}
  </Stack>
);

type MediaRenderProps = {
  conversationId?: string;
  attachment: SendFileItem;
  isSecure: boolean;
  onUpdateAttachmentLoadError?: React.Dispatch<
    React.SetStateAction<AttachmentLoadError>
  >;
  zoom?: number;
  onZoom?: (newZoom: number) => void;
  controlsVisible?: boolean;
};

type VideoMediaRenderProps = {
  conversationId?: string;
  attachment: SendVideosType;
  isSecure: boolean;
  controlsVisible?: boolean;
};

const VideoMediaRender: FC<VideoMediaRenderProps> = ({
  conversationId,
  attachment,
  isSecure,
  controlsVisible,
}) => {
  const { ref, dimensions } = useDimensions();
  const isReady = dimensions.width > 0 && dimensions.height > 0;
  const { width, height } = getScaledDimensions(
    dimensions.height,
    dimensions.width,
    attachment.video_html_width,
    attachment.video_html_height,
  );
  const sxProps: SxProps = {
    height,
    width,
    '& video': { objectFit: 'contain', borderRadius: 1, height, width },
  };

  return (
    <Stack
      ref={ref}
      sx={{
        width: '100%',
        height: '100%',
        alignItems: 'center',
        justifyContent: 'center',
      }}
    >
      {isReady && (
        <PlayerVideo
          conversationId={conversationId}
          isSecure={isSecure}
          url={attachment.local_video_url || attachment.video_url}
          thumbUrl={attachment.thumb_url}
          sxSecure={sxProps}
          sxDefault={sxProps}
          controlsVisible={controlsVisible}
        />
      )}
    </Stack>
  );
};

const MediaRender: FC<MediaRenderProps> = ({
  conversationId,
  attachment,
  isSecure,
  onUpdateAttachmentLoadError,
  zoom = 1,
  onZoom,
  controlsVisible,
}) => {
  const { transform, cursor, isDragging, handlers } = useZoomPan(zoom);

  if (isImageAttachment(attachment)) {
    const imageSx = {
      width: '100%',
      height: '100%',
      maxWidth: '100%',
      maxHeight: '100%',
      objectFit: 'contain',
      borderRadius: 1,
    } as const;

    const handleDoubleClick = () => {
      onZoom?.(zoom > 1 ? 1 : 2);
    };

    return (
      <MediaWrapper>
        <Stack
          {...handlers}
          onDoubleClick={handleDoubleClick}
          sx={{
            width: '100%',
            height: '100%',
            alignItems: 'center',
            justifyContent: 'center',
            cursor,
            transform,
            transformOrigin: 'center',
            transition: isDragging ? 'none' : 'transform 0.15s ease',
            userSelect: 'none',
          }}
        >
          <LazySecureAwareImage
            conversationId={conversationId}
            isSecure={isSecure}
            url={attachment.image_url}
            alt={attachment.filename}
            onUpdateAttachmentLoadError={onUpdateAttachmentLoadError}
            sxSecure={imageSx}
            sxDefault={imageSx}
          />
        </Stack>
      </MediaWrapper>
    );
  }

  if (isVideoAttachment(attachment)) {
    return (
      <VideoMediaRender
        conversationId={conversationId}
        attachment={attachment}
        isSecure={isSecure}
        controlsVisible={controlsVisible}
      />
    );
  }

  return null;
};

export default MediaRender;
