import { type FC, useEffect, useState } from 'react';
import { useFormContext } from 'react-hook-form';

import i18next from 'i18next';
import Stack from '@material-hu/mui/Stack';
import Typography from '@material-hu/mui/Typography';

import HuCardContainer from '@material-hu/components/design-system/CardContainer';
import { type FileCardType } from '@material-hu/components/design-system/FileCard/types';
import useHuSnackbar from '@material-hu/components/design-system/Snackbar';
import HuFormUploader from '@material-hu/components/design-system/Uploader/form';

import { MAX_ATTACHMENTS_B } from 'src/constants/posts';
import { useAuth } from 'src/contexts/JWTContext';
import { useUpdateFilesInRequest } from 'src/hooks/queryHooks/vacations';
import { getPolicyTypeById } from 'src/pages/dashboard/timeOff/queries';
import { uploadAllFiles } from 'src/services/attachments';
import {
  AttachmentRequirement,
  type TimeOffAttachment,
  type VacationStatus,
} from 'src/types/vacations';
import { useLokaliseTranslation } from 'src/utils/i18n';
import { checkSameNamefiles, processFilesVacations } from 'src/utils/vacations';

export type DropZoneVacationsProps = {
  name: string;
  policyTypeId: number;
  disabled?: boolean;
  isManagerView?: boolean;
  requestId?: number;
  requestState?: VacationStatus;
  uploadFiles?: boolean;
  requestAttachments?: TimeOffAttachment[];
  userId?: number;
};

export const DropZoneVacations: FC<DropZoneVacationsProps> = props => {
  const {
    requestId,
    policyTypeId,
    uploadFiles = false,
    requestState,
    requestAttachments,
    userId,
    disabled,
  } = props;
  const [loadingUploadFiles, setLoadingUploadFiles] = useState(false);

  const { t } = useLokaliseTranslation(['time_off', 'validations']);
  const { enqueueSnackbar } = useHuSnackbar();
  const { user } = useAuth();
  const { setValue, watch, getValues, clearErrors } = useFormContext();

  const policyType = getPolicyTypeById(policyTypeId, userId || user?.id!);
  const requiredFiles =
    policyType?.attachmentRequirement === AttachmentRequirement.REQUIRED;

  const files = watch('files') || [];

  const { mutate, isLoading: isLoadingUpdateFiles } = useUpdateFilesInRequest({
    requestId: requestId!,
    requestState: requestState!,
    requestAttachments: requestAttachments!,
  });

  const onHandleRemove = (file: FileCardType) => {
    if (file.status === 'uploading') {
      return;
    }
    if (uploadFiles) {
      const filesToFilter = getValues('files');
      const newFiles = filesToFilter.reduce(
        (acc: TimeOffAttachment[], elem: FileCardType) => {
          if (elem.attachment?.name === file.attachment?.name) {
            return acc;
          }
          return [...acc, elem.attachment];
        },
        [],
      );
      mutate(newFiles);
    }
  };

  const onHandleDropAccepted = async (filesAccepted: File[]) => {
    const oldAttachments = files.map((file: FileCardType) => file.attachment);
    const filesWithSameName = checkSameNamefiles(filesAccepted, oldAttachments);
    if (filesWithSameName) {
      setValue('files', files);
      return enqueueSnackbar({
        title: t('DUPLICATE_NAME_ERROR'),
        variant: 'error',
      });
    }
    if (uploadFiles) {
      setLoadingUploadFiles(true);
      const newAttachments = await processFilesVacations(filesAccepted);
      const uploadedAttachments = await uploadAllFiles(newAttachments);

      const allAttachments = [...oldAttachments, ...uploadedAttachments];

      mutate(allAttachments);
    }
    setLoadingUploadFiles(false);
  };

  const loadingFiles = isLoadingUpdateFiles || loadingUploadFiles;

  useEffect(() => {
    if (!requiredFiles) {
      clearErrors('files');
    }
  }, [requiredFiles, clearErrors]);

  const fileRule = {
    required: {
      value: requiredFiles,
      message: i18next.t('validations:not_empty'),
    },
  };

  if (
    !policyTypeId ||
    policyType?.attachmentRequirement === AttachmentRequirement.NONE
  ) {
    return null;
  }

  const disabledToUploadFiles =
    loadingFiles || isLoadingUpdateFiles || disabled;

  return (
    <HuCardContainer
      fullWidth
      color="grey"
    >
      <Stack>
        <Stack>
          <Typography
            variant="globalS"
            sx={{
              fontWeight: 'fontWeightSemiBold',
            }}
          >
            {t('documentation')}
          </Typography>
          <Typography
            variant="globalXS"
            sx={{
              color: ({ palette }) => palette.new.text.neutral.lighter,
            }}
          >
            {policyType?.attachmentInstructions}
          </Typography>
        </Stack>
        <HuFormUploader
          rules={fileRule}
          name="files"
          fileCardProps={{
            onRemove: file => onHandleRemove(file),
            disabled: disabledToUploadFiles,
          }}
          uploaderProps={{
            fileSizeLimit: MAX_ATTACHMENTS_B,
            sx: {
              '& > :first-child > .MuiStack-root': {
                backgroundColor: ({ palette }) =>
                  palette.new.background.elements.default,
              },
              '& .MuiTypography-root': {
                maxWidth: 300,
              },
            },
            disabled: disabledToUploadFiles,
            onDropAccepted: filesAccepted =>
              onHandleDropAccepted(filesAccepted),
            uploadFunction: file =>
              new Promise(resolve => {
                resolve({
                  status: uploadFiles ? 'uploading' : 'success',
                  file,
                });
              }),
          }}
        />
      </Stack>
    </HuCardContainer>
  );
};

export default DropZoneVacations;
