import React, { useCallback, 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, { ExtendControlType } from 'braft-editor'

// 引入编辑器样式
import 'braft-editor/dist/index.css'

import classNames from 'classnames'
import { MessageFu } from '@/utils/message'
import { fileDomInitialFu } from '@/utils/domShow'
import { forwardRef, useImperativeHandle } from 'react'
import { API_upFile } from '@/store/action/layout'
import ZupAudio, { ZupAudioType } from '../ZupAudio'
import { Button, Checkbox, Input } from 'antd'
import { ArrowDownOutlined, DeleteOutlined, ArrowUpOutlined } from '@ant-design/icons'
import MyPopconfirm from '../MyPopconfirm'

export type SectionArrType = {
  id: number
  name: string
  txt: any
  fileInfo: ZupAudioType
}

type Props = {
  check: boolean //表单校验，为fasle表示不校验
  dirCode: string //文件的code码
  isLook: boolean //是否是查看进来
  ref: any //当前自己的ref，给父组件调用
  myUrl: string //上传的api地址
  isOne?: boolean //只显示单个富文本
  upAudioBtnNone?: boolean //是否能上传无障碍音频
  video?: boolean //是否能上传视频
}

function ZRichTexts(
  { check, dirCode, isLook, myUrl, isOne = false, upAudioBtnNone = false, video = true }: Props,
  ref: any
) {
  const [sectionArr, setSectionArr] = useState<SectionArrType[]>([
    {
      id: Date.now(),
      name: '',
      txt: BraftEditor.createEditorState(''),
      fileInfo: { fileName: '', filePath: '' }
    }
  ])

  // 是否按章节发布
  const [isSection, setIsSection] = useState(false)

  // 当前上传 图片
  const nowIndexRef = useRef(0)

  // 判断 富文本是否为空
  const isTxtFlag = useMemo(() => {
    let flag = false

    // 不是按章节发布，检查第一个富文本
    if (!isSection) {
      const txt = sectionArr[0].txt.toText()
      const txtHtml = sectionArr[0].txt.toHTML()
      const txtRes = txt.replaceAll('\n', '').replaceAll(' ', '')
      if (!txtRes && !txtHtml.includes('class="media-wrap')) flag = true
    } else {
      // 按章节发布  检查 所有的 标题 和富文本
      sectionArr.forEach(v => {
        if (!v.name) flag = true
        const txt = v.txt.toText()
        const txtHtml = sectionArr[0].txt.toHTML()
        const txtRes = txt.replaceAll('\n', '').replaceAll(' ', '')
        if (!txtRes && !txtHtml.includes('class="media-wrap')) flag = true
      })
    }

    return flag
  }, [isSection, sectionArr])

  const myInput = useRef<HTMLInputElement>(null)
  const myInput1 = useRef<HTMLInputElement>(null)

  // 上传
  const handeUpPhoto = useCallback(
    async (e: React.ChangeEvent<HTMLInputElement>, type: 'img' | 'video') => {
      if (e.target.files) {
        // 拿到files信息
        const filesInfo = e.target.files[0]

        const isVideo = filesInfo?.name.endsWith('.mp4')
        if (isVideo && type === 'img') {
          return MessageFu.warning('图片只支持png、jpg和jpeg格式!')
        } else if (!isVideo && type === 'video') {
          return MessageFu.warning('视频只支持mp4格式!')
        }

        if (!video && isVideo) return MessageFu.warning('不支持上传视频!')

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

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

        // 大小校验
        if (filesInfo.size > mediaConfig.maxSize * 1024 * 1024) {
          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(sectionArr[nowIndexRef.current].txt, [
              {
                type: mediaConfig.mediaType,
                url: res.data.url
              }
            ])
            const arr = [...sectionArr]
            arr[nowIndexRef.current].txt = newTxt
            setSectionArr(arr)
          }
          fileDomInitialFu()
        } catch (error) {
          fileDomInitialFu()
        }
      }
    },
    [dirCode, myUrl, sectionArr, video]
  )

  // 让父组件调用的 回显 富文本
  const ritxtShowFu = useCallback((val: any) => {
    if (val) {
      setIsSection(val.isSection || false)
      if (val.txtArr) {
        const arr = val.txtArr.map((v: any) => ({
          ...v,
          txt: BraftEditor.createEditorState(v.txt)
        }))
        setSectionArr(arr)
      }
    }
  }, [])

  // 让父组件调用的返回 富文本信息 和 表单校验 isTxtFlag为ture表示未通过校验
  const fatherBtnOkFu = useCallback(() => {
    const arr: any[] = []

    sectionArr.forEach((v, i) => {
      arr.push({
        ...v,
        txt: v.txt.toHTML()
      })
    })

    const obj = {
      isSection: isSection, //是否按章节发布
      txtArr: arr
    }

    return { val: obj, flag: isTxtFlag }
  }, [isSection, isTxtFlag, sectionArr])

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

  // 点击新增章节
  const addSectionFu = useCallback(() => {
    if (sectionArr.length >= 20) return MessageFu.warning('最多存在20个章节')
    setSectionArr([
      ...sectionArr,
      {
        id: Date.now(),
        name: '',
        txt: BraftEditor.createEditorState(''),
        fileInfo: { fileName: '', filePath: '' }
      }
    ])
  }, [sectionArr])

  // 章节音频上传成功
  const upSectionFu = useCallback(
    (info: ZupAudioType, index: number) => {
      const arr = [...sectionArr]
      arr[index].fileInfo = info
      setSectionArr(arr)
    },
    [sectionArr]
  )

  // 章节音频删除
  const delSectionFu = useCallback(
    (index: number) => {
      // console.log("ppppppppp", index);

      const arr = [...sectionArr]
      arr[index].fileInfo = { fileName: '', filePath: '' }
      setSectionArr(arr)
    },
    [sectionArr]
  )

  // 整个章节的删除
  const delSectionAllFu = useCallback(
    (id: number) => {
      setSectionArr(sectionArr.filter(v => v.id !== id))
    },
    [sectionArr]
  )

  // 整个章节的位移
  const moveSectionFu = useCallback(
    (index: number, num: number) => {
      const arr = [...sectionArr]
      const temp = arr[index]
      arr[index] = arr[index + num]
      arr[index + num] = temp
      setSectionArr(arr)
    },
    [sectionArr]
  )

  // 单个富文本是否输入完整
  const isOneTxtFlag = useCallback(
    (name: string, txt: any) => {
      let flag = false
      if (!name && isSection) flag = true
      const txt2 = txt.toText()
      const txtHtml = txt.toHTML()
      const txtRes = txt2.replaceAll('\n', '').replaceAll(' ', '')
      if (!txtRes && !txtHtml.includes('class="media-wrap')) flag = true
      return flag
    },
    [isSection]
  )

  const extendControls: ExtendControlType[] = [
    'separator',
    {
      key: 'my-button',
      type: 'button',
      title: `上传图片`,
      className: 'my-button', // 指定按钮的样式名
      html: null, // 指定在按钮中渲染的html字符串
      text: `上传图片`,
      onClick: () => {
        nowIndexRef.current = 0
        myInput.current?.click()
      }
    }
  ]
  const videoControlBtn: ExtendControlType = {
    key: 'my-button1',
    type: 'button',
    title: `上传视频`,
    className: 'my-button', // 指定按钮的样式名
    html: null, // 指定在按钮中渲染的html字符串
    text: `上传视频`,
    onClick: () => {
      nowIndexRef.current = 0
      myInput1.current?.click()
    }
  }

  return (
    <div className={styles.ZRichTexts}>
      <input
        id='upInput'
        type='file'
        accept={`.png,.jpg,.jpeg`}
        ref={myInput}
        onChange={e => handeUpPhoto(e, 'img')}
      />
      <input
        id='upInput'
        type='file'
        accept={`.mp4`}
        ref={myInput1}
        onChange={e => handeUpPhoto(e, 'video')}
      />

      <div
        className={classNames('formRightZW', isLook ? 'formRightZWLook' : '')}
        style={{ display: isSection ? 'block' : 'none' }}
      >
        {isOne ? (
          <div></div>
        ) : (
          <Checkbox checked={isSection} onChange={e => setIsSection(e.target.checked)}>
            按章节发布
          </Checkbox>
        )}

        {isSection && (
          <Button hidden={isLook} type='primary' onClick={addSectionFu}>
            新增章节
          </Button>
        )}
      </div>

      <div className={classNames('txtBox', isLook ? 'txtBoxLook' : '')}>
        {sectionArr.map((item, index) => (
          <div
            className={classNames(
              'zztxtRow',
              isOneTxtFlag(item.name, item.txt) && check ? 'zztxtRowErr' : ''
            )}
            key={item.id}
            hidden={!isSection && index > 0}
          >
            {/* 顶部 */}
            <div className='zztxtRow1' hidden={!isSection && index === 0}>
              <div className='zztxtRow1_1'>
                <div className='zztxtRow1_1_1'>章节 {index + 1}</div>
                <div className='zztxtRow1_1_2'>
                  标题：
                  <Input
                    readOnly={isLook}
                    value={item.name}
                    placeholder='请输入内容'
                    maxLength={100}
                    showCount
                    style={{ width: 400 }}
                    onChange={e => {
                      const arr = [...sectionArr]
                      arr[index].name = e.target.value.replace(/\s+/g, '')
                      setSectionArr(arr)
                    }}
                  />
                  &emsp;
                  <Button
                    hidden={isLook}
                    onClick={() => {
                      nowIndexRef.current = index
                      myInput.current?.click()
                    }}
                  >
                    上传图片
                  </Button>
                </div>
              </div>
              <div className='zztxtRow1_2'>
                <ZupAudio
                  fileInfo={item.fileInfo}
                  upDataFu={info => upSectionFu(info, index)}
                  delFu={() => delSectionFu(index)}
                  dirCode={dirCode}
                  myUrl={myUrl}
                  isLook={isLook}
                />
                &emsp;
                <div
                  hidden={isLook}
                  className={classNames('zztxtRow1_2Icon', index === 0 ? 'zztxtRow1_2IconNo' : '')}
                  onClick={() => moveSectionFu(index, -1)}
                >
                  <ArrowUpOutlined title='上移' />
                </div>
                &emsp;
                <div
                  hidden={isLook}
                  className={classNames(
                    'zztxtRow1_2Icon',
                    index === sectionArr.length - 1 ? 'zztxtRow1_2IconNo' : ''
                  )}
                  onClick={() => moveSectionFu(index, 1)}
                >
                  <ArrowDownOutlined title='下移' />
                </div>
                &emsp;
                {isLook || sectionArr.length <= 1 ? null : (
                  <MyPopconfirm
                    txtK='删除'
                    onConfirm={() => delSectionAllFu(item.id)}
                    Dom={<DeleteOutlined title='删除' className='ZTbox2X' />}
                  />
                )}
              </div>
            </div>
            {/* 主体 */}
            <BraftEditor
              readOnly={isLook}
              placeholder='请输入内容'
              value={item.txt}
              onChange={e => {
                const arr = [...sectionArr]
                arr[index].txt = e
                setSectionArr(arr)
              }}
              imageControls={['remove']}
              extendControls={
                isLook ? [] : video ? [...extendControls, videoControlBtn] : extendControls
              }
            />
          </div>
        ))}
      </div>
      {video && <div className='tip'>视频格式要求，仅支持MP4格式的视频文件，大小不得超过500M</div>}
      <div className={classNames('noUpThumb', check && isTxtFlag ? 'noUpThumbAc' : '')}>
        {`请完整输入${isSection ? '标题/' : ''}正文!`}
      </div>
    </div>
  )
}

export default forwardRef(ZRichTexts)
