import { forwardRef, type MouseEvent, useState } from 'react';
import { type DropEvent } from 'react-dropzone';

import { FormControl, Stack } from '@mui/material';

import { megabytesToBytes } from '../../../utils/bytes';
import { urlToFile } from '../../../utils/files';
import CustomHelperText from '../../design-system/Inputs/Base/CustomHelperText';
import CustomLabel from '../../design-system/Inputs/Base/CustomLabel';

import CoverPictureActions from './components/CoverPictureActions';
import CoverPictureImage from './components/CoverPictureImage';
import useHandleCrop from './hooks/useHandleCrop';
import useHandleDropzone from './hooks/useHandleDropzone';
import { type CoverPictureUploaderProps } from './types';

const CoverPictureUploader = forwardRef<
  HTMLDivElement,
  CoverPictureUploaderProps
>(
  (
    {
      sx,
      label,
      value,
      defaultSrc,
      helperText,
      recommendedSizeTooltip,
      recommendedWidth,
      recommendedHeight,
      onChange = () => null,
      onDropAccepted = () => null,
      onDropRejected = () => null,
      maxSize = megabytesToBytes(50),
      error,
      disabled = false,
      onFileChange = () => null,
      aspectRatio = '2/1',
    },
    ref,
  ) => {
    const [loadingReposition, setLoadingReposition] = useState(false);

    const { modal, showModal } = useHandleCrop({
      recommendedWidth,
      recommendedHeight,
      onSave: (file: File, event: MouseEvent<HTMLButtonElement>) => {
        onChange({ ...value, cropped: file }, event);
        onFileChange(file, event);
      },
    });

    const { getInputProps, open } = useHandleDropzone({
      maxSize,
      disabled,
      onDropRejected,
      onDropAccepted: (file: File, event: DropEvent) => {
        onChange({ cropped: null, original: file }, event);
        showModal({ file });
        onDropAccepted(file, event);
      },
    });

    const handleDelete = (event: MouseEvent<HTMLButtonElement>) => {
      onChange({ cropped: null, original: null }, event);
    };

    const handleReposition = async () => {
      setLoadingReposition(true);

      const file = value?.original || value?.cropped;
      const fileToCrop =
        typeof file === 'string' ? await urlToFile(file) : file;

      showModal({ file: fileToCrop! });

      setLoadingReposition(false);
    };

    return (
      <>
        {modal}
        <Stack
          ref={ref}
          className="HuCoverPictureUploader-root"
          component={FormControl}
          error={error}
          sx={{ gap: 1, width: '100%', ...sx }}
        >
          <Stack sx={{ gap: 1.5 }}>
            <CustomLabel label={label} />
            <CoverPictureImage
              image={value?.cropped || defaultSrc}
              aspectRatio={aspectRatio}
            />
          </Stack>
          {error && (
            <CustomHelperText
              value=""
              helperText={helperText}
            />
          )}
          <CoverPictureActions
            onChange={open}
            onDelete={handleDelete}
            onReposition={handleReposition}
            inputProps={getInputProps()}
            loadingReposition={loadingReposition}
            isEdit={!!value?.cropped}
            disabled={disabled}
            recommendedSizeTooltip={recommendedSizeTooltip}
          />
        </Stack>
      </>
    );
  },
);

CoverPictureUploader.displayName = 'CoverPictureUploader';

export default CoverPictureUploader;
