import React, {
  useCallback,
  useEffect,
  useMemo,
  useRef,
  useState,
} from "react";
import styles from "./index.module.scss";

// 引入编辑器组件

// 安装---npm install braft-editor --save --force
// npm install braft-utils --save --force
import { ContentUtils } from "braft-utils";
import BraftEditor from "braft-editor";
// 引入编辑器样式
import "braft-editor/dist/index.css";

import classNames from "classnames";
import { MessageFu } from "@/utils/message";
import { fileDomInitialFu } from "@/utils/domShow";
import { baseURL } from "@/utils/http";

import { forwardRef, useImperativeHandle } from "react";
import { API_upFile } from "@/store/action/layout";

type Props = {
  check: boolean; //表单校验，为fasle表示不校验
  dirCode: string; //文件的code码
  isLook: boolean; //是否是查看进来
  ref: any; //当前自己的ref，给父组件调用
  myUrl: string; //上传的api地址
  full?: boolean;
};

function ZRichText({ check, dirCode, isLook, myUrl, full }: Props, ref: any) {
  // 添加 上传 图片的dom
  useEffect(() => {
    setTimeout(() => {
      const dom = document.querySelector(".bf-controlbar")!;
      const div = document.createElement("div");
      div.className = "upImgBox";
      // div.title = "上传图片";
      div.innerHTML = "上传图片/视频";
      div.onclick = async () => {
        myInput.current?.click();
      };
      dom.appendChild(div);
    }, 20);

    // 监听 富文本 的 class 变化，在全屏的时候会 富文本会添加上 fullscreen 的类
    // 修复顶部样式冲突问题

    const editorDom = document.querySelector(".bf-container") as HTMLDivElement;

    const observer = new MutationObserver(() => {
      // console.log("change");
      const dom = document.querySelector(".layoutRightTop") as HTMLDivElement;

      if (editorDom.className.includes("fullscreen")) dom.style.zIndex = "-1";
      else dom.style.zIndex = "100";
    });

    observer.observe(editorDom, {
      attributes: true,
    });

    // 销毁监听
    return () => {
      observer.disconnect();
    };
  }, []);

  useEffect(() => {
    const controlbarDom = document.querySelectorAll(".txtBox .bf-controlbar ");
    const contentDom = document.querySelectorAll(".txtBox .bf-content ");
    if (controlbarDom) {
      controlbarDom.forEach((v: any) => {
        v.style.display = isLook ? "none" : "block";
      });
      contentDom.forEach((v: any) => {
        v.style.height = isLook ? "100%" : "";
      });
    }
  }, [isLook]);

  // 编辑器文本
  const [editorValue, setEditorValue] = useState(
    // 初始内容
    BraftEditor.createEditorState("")
  );

  // 判断 富文本是否为空
  const isTxtFlag = useMemo(() => {
    const txt: string = editorValue.toHTML();
    if (
      txt.replaceAll("<p>", "").replaceAll("</p>", "").replaceAll(" ", "") ===
      ""
    ) {
      return true;
    } else return false;
  }, [editorValue]);

  const myInput = useRef<HTMLInputElement>(null);

  // 上传图片
  const handeUpPhoto = useCallback(
    async (e: React.ChangeEvent<HTMLInputElement>) => {
      if (e.target.files) {
        // 拿到files信息
        const filesInfo = e.target.files[0];

        let type = ["image/jpeg", "image/png", "video/mp4"];
        let size = 5;
        let txt = "图片只支持png、jpg和jpeg格式!";
        let txt2 = "图片最大支持5M!";

        const isVideoFlag = filesInfo.name.endsWith(".mp4");

        // 校验格式
        if (!type.includes(filesInfo.type)) {
          e.target.value = "";
          if (isVideoFlag) {
            // 上传视频
            size = 500;
            txt = "视频只支持mp4格式!";
            txt2 = "视频最大支持500M!";
          }

          return MessageFu.warning(txt);
        }
        // 校验大小
        if (filesInfo.size > size * 1024 * 1024) {
          e.target.value = "";
          return MessageFu.warning(txt2);
        }
        // 创建FormData对象
        const fd = new FormData();
        // 把files添加进FormData对象（‘photo’为后端需要的字段）
        fd.append("type", isVideoFlag ? "video" : "img");
        fd.append("dirCode", dirCode);
        fd.append("file", filesInfo);

        e.target.value = "";

        try {
          const res = await API_upFile(fd, myUrl);
          if (res.code === 0) {
            MessageFu.success("上传成功!");
            // 在光标位置插入图片
            const newTxt = ContentUtils.insertMedias(editorValue, [
              {
                type: "IMAGE",
                url: baseURL + res.data.filePath,
              },
            ]);

            setEditorValue(newTxt);
          }
          fileDomInitialFu();
        } catch (error) {
          fileDomInitialFu();
        }
      }
    },
    [dirCode, editorValue, myUrl]
  );

  // 让父组件调用的 回显 富文本
  const ritxtShowFu = useCallback((val: string) => {
    setEditorValue(BraftEditor.createEditorState(val));
  }, []);

  // 让父组件调用的返回 富文本信息 和 表单校验 isTxtFlag为ture表示未通过校验
  const fatherBtnOkFu = useCallback(() => {
    return { val: editorValue.toHTML(), flag: isTxtFlag };
  }, [editorValue, isTxtFlag]);

  // 可以让父组件调用子组件的方法
  useImperativeHandle(ref, () => ({
    ritxtShowFu,
    fatherBtnOkFu,
  }));

  return (
    <div className={styles.ZRichText} style={{ width: full ? "100%" : "" }}>
      <input
        id="upInput"
        type="file"
        accept=".png,.jpg,.jpeg,.mp4"
        ref={myInput}
        onChange={(e) => handeUpPhoto(e)}
      />

      <div className="txtBox">
        <BraftEditor
          readOnly={isLook}
          placeholder="请输入内容"
          value={editorValue}
          onChange={(e) => setEditorValue(e)}
          imageControls={["remove"]}
        />
      </div>
      <div
        className={classNames(
          "noUpThumb",
          check && isTxtFlag ? "noUpThumbAc" : ""
        )}
      >
        请输入正文!
      </div>
    </div>
  );
}

export default forwardRef(ZRichText);
