import { type MouseEvent, useRef, useState } from 'react';
import AvatarEditor from 'react-avatar-editor';

import Button from '@mui/lab/LoadingButton';
import {
  DialogActions,
  DialogContent,
  DialogTitle,
  Slider,
  Stack,
  useMediaQuery,
  useTheme,
} from '@mui/material';
import { IconZoomIn, IconZoomOut } from '@tabler/icons-react';

import useScrollZoom from './hooks/useScrollZoom';
import { type CroppingModalProps } from './types';

const CroppingModal = ({
  file,
  onClose,
  onSave,
  onChangeSlider = () => null,
  recommendedWidth,
  recommendedHeight,
  title,
  cancelLabel,
  saveLabel,
  sliderLabel,
  round = false,
}: CroppingModalProps) => {
  const theme = useTheme();
  const isSmallDevice = useMediaQuery(theme.breakpoints.down('md'));
  const isMobileDevice = useMediaQuery(theme.breakpoints.down('sm'));

  const dimensionIfSmall = isSmallDevice ? 3 : 1.5;
  const dimentionAdjustment = isMobileDevice ? 5 : dimensionIfSmall;
  const adjustedWidth = recommendedWidth / dimentionAdjustment;
  const adjustedHeight = recommendedHeight / dimentionAdjustment;

  const editor = useRef<AvatarEditor>(null);

  const [loading, setLoading] = useState(false);

  const contentRef = useRef<HTMLDivElement>(null);
  const { zoom, setZoom } = useScrollZoom(contentRef);

  const handleChangeSlider = (event: Event, newValue: number | number[]) => {
    onChangeSlider(event, newValue);
    setZoom(newValue as number);
  };

  const handleSave = async (event: MouseEvent<HTMLButtonElement>) => {
    setLoading(true);

    if (!editor?.current) return;

    const dataUrl = editor.current.getImageScaledToCanvas().toDataURL();

    const result = await fetch(dataUrl);
    const blob = await result.blob();
    const newFile = new File([blob], file.name, { type: file.type });

    await onSave(newFile, event);
    onClose();
  };

  return (
    <>
      <DialogTitle
        sx={{ py: 2, px: 3 }}
        variant="globalS"
        fontWeight="fontWeightSemiBold"
      >
        {title}
      </DialogTitle>
      <DialogContent
        ref={contentRef}
        sx={{
          px: 3,
          '&.MuiDialogContent-root': {
            py: 2,
          },
        }}
      >
        <Stack sx={{ gap: 3 }}>
          <AvatarEditor
            ref={editor}
            image={file}
            width={recommendedWidth}
            height={recommendedHeight}
            border={30}
            scale={1 + zoom / 100}
            style={{
              display: 'block',
              marginLeft: 'auto',
              marginRight: 'auto',
              width: adjustedWidth,
              height: adjustedHeight,
            }}
            borderRadius={round ? Infinity : 0}
            color={[0, 0, 0, 0.7]}
          />
          <Stack
            sx={{
              flexDirection: 'row',
              alignItems: 'center',
              justifyContent: 'center',
              gap: 2,
            }}
          >
            <IconZoomOut />
            <Slider
              aria-label={sliderLabel}
              value={zoom}
              onChange={handleChangeSlider}
            />
            <IconZoomIn />
          </Stack>
        </Stack>
      </DialogContent>
      <DialogActions
        sx={{
          p: 3,
          borderTop: `1px solid ${theme.palette.new.border.neutral.default}`,
        }}
      >
        <Button onClick={onClose}>{cancelLabel}</Button>
        <Button
          variant="contained"
          onClick={handleSave}
          loading={loading}
        >
          {saveLabel}
        </Button>
      </DialogActions>
    </>
  );
};

export default CroppingModal;
