import "./UppyUpload.scss";
import React, { useEffect } from "react";
import Uppy, { UploadResult, UppyFile } from "@uppy/core";
import AwsS3Multipart from "@uppy/aws-s3-multipart";
import { useUppy, DragDrop } from "@uppy/react";
import { getVideoDuration } from "utils/photo";
import notification from "antd/lib/notification";
import classNames from "classnames";
import config from "config";

interface Props {
  chilren?: any;
  className?: string;
  forceReset?: boolean;
  durationRestrict?: number;
  minFiles?: number;
  maxFiles?: number;
  acceptFiles?: string[];
  isShowPreview?: boolean;
  setLoading?: (value: boolean) => void;
  setLoadingPercent: (value: number) => void;
  onUploadSuccess?: (file: UppyFile<any>, body: any, uploadURL: string) => void;
  onUploadError?: (args: any) => void;
  onComplete?: (result: UploadResult<any>) => void;
}
const maxRetry = 100; // max retry in 5 minutes (3000 * 100)
let retryUploadCount = 0;

const UppyUpload: React.FC<Props> = ({
  children,
  className,
  minFiles,
  maxFiles,
  durationRestrict,
  acceptFiles,
  forceReset,
  setLoading,
  setLoadingPercent,
  onUploadSuccess,
  onUploadError,
  onComplete,
  isShowPreview = false,
}) => {
  const uppy = useUppy(() => {
    return Uppy<Uppy.StrictTypes>({
      autoProceed: true,
      debug: true,
      restrictions: {
        minNumberOfFiles: minFiles,
        maxNumberOfFiles: maxFiles,
        allowedFileTypes: acceptFiles,
      },
      onBeforeFileAdded: (
        currentFile: UppyFile<any>,
        files: { [key: string]: UppyFile<any> }
      ) => {
        console.log("onBeforeFileAdded:", { currentFile, files });
        return true;
      },
    }).use(AwsS3Multipart, {
      companionUrl: `${config.api.url}/files/companion`,
    });
  });

  useEffect(() => {
    uppy
      .on("file-added", async (file) => {
        const duration = await getVideoDuration(file.data);
        if (!!durationRestrict && duration < durationRestrict) {
          notification.error({
            message: `Please upload the video must greater than ${Math.floor(
              durationRestrict / 60
            )} minute.`,
            description: "",
          });
          typeof setLoading === "function" && setLoading(false);
          uppy.cancelAll();
        }
      })
      .on(
        "upload-success",
        (file: UppyFile<any>, body: any, uploadURL: string) => {
          typeof setLoading === "function" && setLoading(false);
          typeof onUploadSuccess === "function" &&
            onUploadSuccess(file, body, uploadURL);
        }
      )
      .on("complete", (result: UploadResult<any>) => {
        typeof onComplete === "function" && onComplete(result);
      })
      .on("upload-progress", (args) => {
        retryUploadCount = 0;
        const state = uppy.getState();
        typeof setLoadingPercent === "function" &&
          setLoadingPercent(state.totalProgress);
      })
      .on("upload", (args: any) => {
        typeof setLoading === "function" && setLoading(true);
      })
      .on("error", (args: any) => {
        console.error("error callback", args);
        // typeof onUploadError === "function" && onUploadError(args);
      })
      .on("upload-error", (args: any) => {
        console.error("upload error callback", { args, retryUploadCount });
        retryUploadCount++;
        if (retryUploadCount > maxRetry) {
          notification.error({
            message: "Upload error !!!",
            description: "",
          });
          typeof onUploadError === "function" && onUploadError(args);
          uppy.reset();
          retryUploadCount = 0;
        } else {
          setTimeout(() => {
            uppy.retryAll();
          }, 3000);
        }
      })
      .on("restriction-failed", (file, error) => {
        notification.error({
          message: error?.message,
          description: "",
        });
        // do some customized logic like showing system notice to users
        console.error("upload error callback", { file, error });
      });
    return () => {
      uppy.close();
    };
  }, []);

  useEffect(() => {
    if (!forceReset) return;
    uppy.reset();
  }, [forceReset]);

  const videoContainerClass = classNames({
    "video-content__container": true,
    [className || ""]: true,
  });

  const videoCardClass = classNames({
    "video-content__card": true,
    "video-content__card--show-preview": isShowPreview,
  });

  return (
    <React.Fragment>
      <div className={videoContainerClass}>
        <div className={videoCardClass}>
          <DragDrop uppy={uppy} inputName="files[]" />
          {children}
        </div>
      </div>
    </React.Fragment>
  );
};

export default UppyUpload;
