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]

        const isVideo = filesInfo.name.endsWith('.mp4')

        const mediaConfig = isVideo
          ? {
              types: ['video/mp4'],
              maxSize: 500,
              errorText: '视频只支持mp4格式!',
              errorSizeText: '视频最大支持500M!',
              mediaType: 'VIDEO'
            }
          : {
              types: ['image/jpeg', 'image/png'],
              maxSize: 5,
              errorText: '图片只支持png、jpg和jpeg格式!',
              errorSizeText: '图片最大支持5M!',
              mediaType: 'IMAGE'
            }

        // 格式校验
        if (!mediaConfig.types.includes(filesInfo.type)) {
          e.target.value = ''
          return MessageFu.warning(mediaConfig.errorText)
        }

        // 大小校验
        if (filesInfo.size > mediaConfig.maxSize) {
          e.target.value = ''
          return MessageFu.warning(mediaConfig.errorSizeText)
        }

        // 创建FormData对象
        const fd = new FormData()
        // 把files添加进FormData对象（‘photo’为后端需要的字段）
        fd.append('type', isVideo ? '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: mediaConfig.mediaType,
                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)
