import { FC, useEffect, useState } from "react";
import { message } from "antd";
import { Editor, Toolbar } from "@wangeditor/editor-for-react";
import { IDomEditor, IEditorConfig, IToolbarConfig } from "@wangeditor/editor";
import { getBaseURL, requestByPost } from "@dage/service";
import { DageFileAPIResponseType, DageUploadType } from "../DageUpload";
import { ACCEPT, validateFileType } from "../DageUpload/utils";
import { DageEditorProps, InsertFnType } from "./types";
import "@wangeditor/editor/dist/css/style.css";
import { DageLoading } from "../DageLoading";
import { LoadingOutlined } from "@ant-design/icons";
import { assign } from "lodash";

export const DageEditor: FC<DageEditorProps> = ({
  value,
  style,
  className,
  action,
  readOnly,
  fieldName = "file",
  maxImgSize = 2,
  maxVideoSize = 100,
  placeholder = "请输入内容",
  onChange,
  onCreated,
  onDestroyed,
  onFocus,
  onBlur,
  customPaste,
  ...tbConfig
}) => {
  const [uploadLoading, setUploadLoading] = useState(false);
  const [editor, setEditor] = useState<IDomEditor | null>(null);

  const validateFile = (file: File, type: DageUploadType) => {
    if (!validateFileType(file, ACCEPT[type])) {
      message.error("选择的文件类型不正确！");
      return false;
    }

    const size = type === DageUploadType.IMG ? maxImgSize : maxVideoSize;
    // 校验文件大小
    const isLtM = file.size / 1024 / 1024 < size;
    if (!isLtM) {
      message.error(`最大支持 ${size}M!`);
      return false;
    }

    return true;
  };

  const uploadFile = async (file: File, type: DageUploadType) => {
    const formData = new FormData();

    formData.append("type", type);

    if (file instanceof Blob) {
      formData.append(fieldName, file, (file as any).name);
    } else {
      formData.append(fieldName, file);
    }

    const data = await requestByPost<DageFileAPIResponseType>(action, formData);

    return data;
  };

  // 工具栏配置
  const toolbarConfig: Partial<IToolbarConfig> = assign(
    {
      excludeKeys: ["codeBlock", "group-video"],
    },
    tbConfig
  );

  // 编辑器配置
  const editorConfig: Partial<IEditorConfig> = {
    readOnly,
    placeholder,
    MENU_CONF: {
      uploadImage: {
        async customUpload(file: File, insertFn: InsertFnType) {
          if (!validateFile(file, DageUploadType.IMG)) return;

          try {
            setUploadLoading(true);

            const baseUrl = getBaseURL();
            const data = await uploadFile(file, DageUploadType.IMG);

            insertFn(
              `${baseUrl}${data.filePath}`,
              data.fileName,
              data.filePath
            );
          } finally {
            setUploadLoading(false);
          }
        },
      },
      uploadVideo: {
        async customUpload(file: File, insertFn: InsertFnType) {
          if (!validateFile(file, DageUploadType.VIDEO)) return;

          try {
            setUploadLoading(true);

            const baseUrl = getBaseURL();
            const data = await uploadFile(file, DageUploadType.VIDEO);

            insertFn(
              `${baseUrl}${data.filePath}`,
              data.fileName,
              data.filePath
            );
          } finally {
            setUploadLoading(false);
          }
        },
      },
    },
    onCreated,
    onDestroyed,
    onFocus,
    onBlur,
    customPaste,
  };

  useEffect(() => {
    return () => {
      if (editor == null) return;
      editor.destroy();
      setEditor(null);
    };
  }, [editor]);

  return (
    <div
      className={className}
      style={{
        position: "relative",
        border: "1px solid var(--w-e-toolbar-border-color)",
        ...style,
      }}
    >
      <Toolbar
        editor={editor}
        defaultConfig={toolbarConfig}
        mode="default"
        style={{ borderBottom: "1px solid var(--w-e-toolbar-border-color)" }}
      />
      <Editor
        defaultConfig={editorConfig}
        value={value}
        onCreated={setEditor}
        onChange={(editor) => onChange?.(editor.getHtml())}
        mode="default"
        style={{ height: "500px", overflowY: "hidden" }}
      />

      {uploadLoading && (
        <DageLoading
          indicator={<LoadingOutlined style={{ fontSize: 30 }} spin />}
        />
      )}
    </div>
  );
};

export * from "./types";
