import { type FC, type PropsWithChildren } from 'react';
import { useDropzone } from 'react-dropzone';
import { useParams } from 'react-router';

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

import useSnackbar from '@material-hu/components/design-system/Snackbar';

import { logEvent } from 'src/config/amplitude';
import useFeatureFlag from 'src/hooks/useFeatureFlag';
import {
  CONVERSATIONS_GORUP_INFO_ID,
  CONVERSATIONS_THREAD_FOOTER_ID,
  MAX_MEDIA_SIZE_MB,
  MEDIA_ORIGIN,
} from 'src/pages/dashboard/Conversations/constants';
import { Format } from 'src/pages/dashboard/Conversations/types';
import { EventName } from 'src/types/amplitude';
import { mimes } from 'src/types/attachments';
import { FeatureFlags } from 'src/types/featureFlags';
import { isValidFilesSizeChatsV2 } from 'src/utils/attachments';
import { bytesFrom } from 'src/utils/bytes';
import { isImage, isVideo } from 'src/utils/files';
import { useLokaliseTranslation } from 'src/utils/i18n';

import { useSendAttachments } from '../../contexts/SendAttachmentsContext';

import { MAX_FILES_ATTACHMENTS } from './ConversationsThreadFooter';

type DropZoneConversationsProps = PropsWithChildren<{
  sx?: SxProps;
}>;

const OFFSET_HEIGHT = 144;

const DropZoneConversations: FC<DropZoneConversationsProps> = props => {
  const { children, sx } = props;

  const { t } = useLokaliseTranslation('chat');
  const { id } = useParams();
  const { enqueueSnackbar } = useSnackbar();
  const blockSendFiles = useFeatureFlag(FeatureFlags.BLOCK_FILES_CHATS_V2);
  const maxMediaSize =
    useFeatureFlag<number>(FeatureFlags.CHATS_V2_MAX_MEDIA_SIZE_MB) ??
    MAX_MEDIA_SIZE_MB;
  const { uploadFiles, attachments } = useSendAttachments();

  const getMediaType = (droppedFiles: File[]) => {
    const hasImages = droppedFiles.some(
      file => isImage(file) && file.type !== mimes.SVG,
    );
    const hasVideos = droppedFiles.some(file => isVideo(file));
    const hasFiles = droppedFiles.some(
      file => (!isImage(file) && !isVideo(file)) || file.type === mimes.SVG,
    );

    if (hasImages && !hasVideos && !hasFiles) return 'image';
    if (hasVideos && !hasImages && !hasFiles) return 'video';
    if (hasFiles && !hasImages && !hasVideos) return 'file';
    if (hasImages && hasVideos && !hasFiles) return 'imagesAndVideos';
    if (hasImages && hasFiles && !hasVideos) return 'imagesAndFile';
    if (hasVideos && hasFiles && !hasImages) return 'videosAndFile';
    if (hasImages && hasVideos && hasFiles) return 'imagesAndVideosAndFile';

    return '';
  };

  const handleDrop = (filesToAdd: File[]) => {
    const isValidSendFiles = isValidFilesSizeChatsV2(
      filesToAdd,
      bytesFrom(maxMediaSize, 'MB'),
    );

    if (!isValidSendFiles) {
      enqueueSnackbar({
        title: t('chat:files.max_limit_files', {
          max: `${maxMediaSize}MB`,
        }),
        variant: 'error',
      });
      return;
    }

    if (filesToAdd.length + attachments.length > MAX_FILES_ATTACHMENTS) {
      enqueueSnackbar({
        title: t('chat:files.limit_count_files', {
          count: MAX_FILES_ATTACHMENTS,
        }),
        variant: 'error',
      });
      return;
    }

    const images = filesToAdd.filter(
      file => isImage(file) && file.type !== mimes.SVG,
    );
    const videos = filesToAdd.filter(file => isVideo(file));
    const others = filesToAdd.filter(
      file => (!isImage(file) && !isVideo(file)) || file.type === mimes.SVG,
    );

    if (images.length > 0) uploadFiles(images, Format.IMAGE);
    if (videos.length > 0) uploadFiles(videos, Format.VIDEO);
    if (others.length > 0) uploadFiles(others, Format.FILE);

    const mediaType = getMediaType(filesToAdd);

    logEvent(EventName.CHATS_2_MESSAGE_MEDIA_ATTACHED, {
      conversationId: id,
      mediaQuantity: filesToAdd.length,
      mediaOrigin: MEDIA_ORIGIN.FILE_EXPLORER,
      mediaType: mediaType,
    });
  };

  const { getRootProps, getInputProps, isDragActive } = useDropzone({
    noClick: true,
    disabled: blockSendFiles,
    onDrop: handleDrop,
    onDropRejected: () => {
      enqueueSnackbar({ title: t('ERROR_DRAG_AND_DROP'), variant: 'error' });
    },
  });

  const conversationsFooterWidth =
    document.getElementById(CONVERSATIONS_THREAD_FOOTER_ID)?.offsetWidth || 0;
  const conversationsGroupInfoWith =
    document.getElementById(CONVERSATIONS_GORUP_INFO_ID)?.offsetWidth || 0;

  return (
    <Stack
      {...getRootProps()}
      sx={sx}
    >
      <Stack
        sx={{
          right: `${conversationsGroupInfoWith || 0}px`,
          bottom: 0,
          position: 'fixed',
          width: `${conversationsFooterWidth}px`,
          height: `calc(100vh - ${OFFSET_HEIGHT}px)`,
          zIndex: 3,
          backgroundColor: theme => theme.palette.new.background.layout.default,
          opacity: isDragActive ? 1 : 0,
          visibility: isDragActive ? 'visible' : 'hidden',
          pointerEvents: isDragActive ? 'auto' : 'none',
          transition: 'opacity 200ms ease, visibility 200ms ease',
        }}
      >
        <Stack
          sx={{
            height: '100%',
            p: 2,
            cursor: 'pointer',
          }}
        >
          <Stack
            sx={{
              borderRadius: 1,
              border: theme =>
                `1px dashed ${theme.palette.base?.blueBrand[400]}`,
              height: '100%',
              width: '100%',
              alignItems: 'center',
              justifyContent: 'center',
              flexDirection: 'column',
            }}
          >
            <Typography
              variant="globalM"
              fontWeight="fontWeightSemiBold"
            >
              {t('drop_file.title')}
            </Typography>
            <Typography variant="globalXS">
              {t('drop_file.description')}
            </Typography>
          </Stack>
        </Stack>
      </Stack>

      {children}
      <input {...getInputProps()} />
    </Stack>
  );
};
export default DropZoneConversations;
