import { Avatar, Box, Button } from '@mui/material';
import { Stack, styled } from '@mui/system';
import { lazy, Suspense, useCallback, useEffect, useRef } from 'react';
import { CloudUpload, Delete, Edit } from '@mui/icons-material';
import { createPortal } from 'react-dom';
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';

const UploaderComponent = lazy(() =>
  import(/* webpackChunkName: "blocklet-uploader" */ '@blocklet/uploader').then((res) => ({
    default: res.Uploader,
  }))
);

type Props = {
  onUploaded: (result: any) => void;
  preview?: string;
  maxFileSize?: number;
  maxNumberOfFiles?: number;
  allowedFileExts?: string[];
  disabled?: boolean;
};

export default function Uploader({
  onUploaded,
  preview = '',
  maxFileSize = undefined,
  maxNumberOfFiles = 1,
  allowedFileExts = ['.png', '.jpeg', '.webp', '.svg', '.jpg'],
  disabled = false,
}: Props) {
  const { locale } = useLocaleContext();
  const uploaderRef = useRef<any>(null);
  const handleOpen = useCallback(() => {
    if (!uploaderRef.current) return;
    uploaderRef.current.open();
  }, []);

  const handleRemove = () => {
    onUploaded({ url: '' });
  };

  useEffect(() => {
    if (uploaderRef.current) {
      const uploader = uploaderRef.current.getUploader();
      uploader.onUploadSuccess((result: any) => {
        onUploaded({ url: result.response.data.url });
      });
    }
  }, [onUploaded]);

  const uploaderPortal = (
    <Suspense fallback={null}>
      <UploaderComponent
        // @ts-ignore
        ref={uploaderRef}
        popup
        onUploadFinish={(result: any) => onUploaded({ url: result.data.url })}
        uploadedProps={{
          onSelectedFiles: (files: any[]) => {
            if (files.length) {
              onUploaded({ url: files[0].fileUrl });
            }
          },
        }}
        coreProps={{
          restrictions: {
            // @ts-ignore
            allowedFileExts,
            maxFileSize,
            maxNumberOfFiles,
          },
        }}
        apiPathProps={{
          uploader: '/api/uploads',
          companion: '/api/companion',
        }}
        locale={locale}
      />
    </Suspense>
  );

  return (
    <>
      {!preview && (
        <Div
          display="flex"
          alignItems="center"
          justifyContent="center"
          onClick={disabled ? undefined : handleOpen}
          sx={{
            position: 'relative',
            cursor: 'pointer',
          }}>
          <CloudUpload style={{ fontSize: 32, color: '#ccc' }} />
        </Div>
      )}
      {preview && (
        <Div
          sx={{
            border: 'none',
            '&:hover': {
              backgroundColor: 'rgba(0, 0, 0, 0.45)',
            },
          }}>
          <Avatar
            src={preview}
            alt="picture"
            variant="square"
            sx={{ width: '100%', height: '100%', borderRadius: '2px' }}
          />
          <Div
            display="flex"
            alignItems="center"
            justifyContent="center"
            sx={{
              position: 'absolute',
              top: 0,
              left: 0,
              width: '100%',
              height: '100%',
              backgroundColor: 'rgba(0, 0, 0, 0.5)',
              opacity: {
                xs: 1,
                md: 0,
              },
              transition: 'opacity 0.3s',
              '&:hover': {
                opacity: 1,
              },
            }}>
            <Stack direction="row">
              <Button
                variant="text"
                onClick={disabled ? undefined : handleOpen}
                startIcon={<Edit />}
                sx={{ minWidth: 20, color: '#fff' }}
              />
              <Button
                variant="text"
                onClick={disabled ? undefined : handleRemove}
                startIcon={<Delete />}
                sx={{ minWidth: 20, color: '#fff' }}
              />
            </Stack>
          </Div>
        </Div>
      )}

      {createPortal(uploaderPortal, document.body)}
    </>
  );
}

const Div = styled(Box)`
  border: 1px solid;
  border-color: ${({ theme }) => theme.palette.grey[300]};
  border-radius: 4px;
  cursor: pointer;
  width: 120px;
  height: 120px;
  position: relative;
`;
