import React, { useCallback, useMemo, useRef, useState } from 'react'
import styles from './index.module.scss'
import { API_upFile } from '@/store/action/layout'
import { MessageFu } from '@/utils/message'
import { fileDomInitialFu } from '@/utils/domShow'
import { Button, Popconfirm } from 'antd'
import {
  UploadOutlined,
  CloseOutlined,
  DownloadOutlined,
  EyeOutlined,
  MenuOutlined
} from '@ant-design/icons'
import classNames from 'classnames'
import { baseURL } from '@/utils/http'
import { authFilesLookFu, FileListType } from './data'
import { DndContext, DragEndEvent, DragOverlay, DragStartEvent, closestCenter } from '@dnd-kit/core'
import {
  SortableContext,
  useSortable,
  verticalListSortingStrategy,
  arrayMove
} from '@dnd-kit/sortable'
import { CSS } from '@dnd-kit/utilities'
import { useInfo } from '@/pages/Zother/InfoContext'
import { Typetable } from '@/pages/Zother/data'
import { fileTypeRes } from '@/utils'
import ImageLazy from '../ImageLazy'
import store from '@/store'
import MyPopconfirm from '../MyPopconfirm'

// ----------------这个组件用于外面一级的附件上传

interface SortableFileItemProps {
  file: FileListType
  onDelete: (id: number) => void
  isLook: boolean
  index: number
  disabled?: boolean
  oneIsCover?: boolean
}
// 修复性能问题：移除不必要的状态和事件处理
const SortableFileItem = React.memo(
  ({ file, onDelete, isLook, index, disabled, oneIsCover }: SortableFileItemProps) => {
    const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({
      id: file.id,
      disabled: disabled || isLook // 修复拖动禁用问题
    })

    const style = {
      transform: CSS.Transform.toString(transform),
      transition,
      opacity: isDragging ? 0.5 : 1
    }

    // 修复按钮点击问题：阻止事件冒泡
    const handleButtonClick = useCallback((e: React.MouseEvent, callback: () => void) => {
      e.stopPropagation() // 修复按钮点击无效问题：阻止事件冒泡到拖拽元素
      callback()
    }, [])

    if (file.type === 'img') {
      return (
        <div
          ref={setNodeRef}
          style={style}
          className={classNames('ZTbox1ImgRow', isDragging ? 'dragging' : '')}
        >
          {/* 修复按钮点击无效问题：将拖拽手柄单独放置，不覆盖操作按钮 */}
          <div
            className='ZTbox1ImgRowDragHandle'
            {...attributes}
            {...listeners}
            style={{ cursor: isLook ? 'default' : 'grab' }}
          >
            {file.thumb || file.filePath ? (
              <ImageLazy noLook={true} width={100} height={100} src={file.thumb || file.filePath} />
            ) : null}
          </div>

          {oneIsCover && index === 0 ? <div className='ZTbox1ImgRowCover'>封面</div> : null}

          <div className='ZTbox1ImgRowIcon'>
            <EyeOutlined
              onClick={e =>
                handleButtonClick(e, () =>
                  store.dispatch({
                    type: 'layout/lookBigImg',
                    payload: {
                      url: baseURL + file.filePath,
                      show: true
                    }
                  })
                )
              }
              rev={undefined}
            />
            <a
              href={baseURL + file.filePath}
              download
              target='_blank'
              rel='noreferrer'
              onClick={e => e.stopPropagation()} // 修复按钮点击无效问题
            >
              <DownloadOutlined rev={undefined} />
            </a>
          </div>

          {!isLook && (
            <MyPopconfirm
              txtK='删除'
              onConfirm={() => onDelete(file.id)}
              Dom={
                <CloseOutlined
                  className='ZTbox1ImgRowX'
                  rev={undefined}
                  onClick={e => e.stopPropagation()} // 修复按钮点击无效问题
                />
              }
            />
          )}
        </div>
      )
    } else {
      return (
        <div
          ref={setNodeRef}
          style={style}
          className={classNames('Z3filesRow', isDragging ? 'dragging' : '')}
        >
          {!isLook && (
            <div className='dragHandle' {...attributes} {...listeners}>
              <MenuOutlined rev={undefined} />
            </div>
          )}
          <div className='Z3files1' title={file.fileName}>
            {file.fileName}
          </div>
          <div className='Z3files2'>
            {authFilesLookFu(file.fileName, '') ? (
              <>
                <EyeOutlined
                  rev={undefined}
                  title='查看'
                  onClick={e =>
                    handleButtonClick(e, () => authFilesLookFu(file.fileName, file.filePath))
                  }
                />
                &emsp;
              </>
            ) : null}
            <a
              title='下载'
              href={baseURL + file.filePath}
              download={file.fileName}
              target='_blank'
              rel='noreferrer'
              onClick={e => e.stopPropagation()} // 修复按钮点击无效问题
            >
              <DownloadOutlined rev={undefined} />
            </a>
            &emsp;
            {!isLook && (
              <Popconfirm
                title='删除后无法恢复，是否删除?'
                okText='删除'
                cancelText='取消'
                onConfirm={() => onDelete(file.id)}
                okButtonProps={{ loading: false }}
              >
                <CloseOutlined
                  rev={undefined}
                  title='删除'
                  onClick={e => e.stopPropagation()} // 修复按钮点击无效问题
                />
              </Popconfirm>
            )}
          </div>
        </div>
      )
    }
  }
)

// ------------------------------------------
type Props = {
  dirCode: string
  myUrl: string
  isLook?: boolean
  fileCheck?: boolean
  fromData?: any
  tips?: string
  size?: number
  maxCount?: number
  oneIsCover?: boolean
  // 默认是修改 files 字段。有可能是下面的附件，使用不同的字段
  filesKey?: 'files' | 'files2'
}

// 修复类型检查问题：统一使用dnd-kit管理所有拖拽
function Z3upFiles({
  isLook = false,
  fileCheck = false,
  dirCode,
  myUrl,
  fromData,
  tips = '单个附件不得超过500M',
  size = 500,
  maxCount = 999,
  oneIsCover,
  filesKey = 'files'
}: Props) {
  const { info, setInfoFu } = useInfo()

  // 修复图片闪动问题：分别管理图片和非图片的排序
  const { imageFiles, otherFiles } = useMemo(() => {
    const arr = info[filesKey] || []
    const imgArr = arr.filter(v => v.type === 'img')
    const otherArr = arr.filter(v => v.type !== 'img')
    return { imageFiles: imgArr, otherFiles: otherArr }
  }, [filesKey, info])

  const fileList = useMemo(() => {
    return [...imageFiles, ...otherFiles]
  }, [imageFiles, otherFiles])

  // 修复性能问题：使用useCallback优化函数记忆
  const setFileList = useCallback(
    (newFiles: FileListType[] | ((prev: FileListType[]) => FileListType[])) => {
      setInfoFu((prevInfo: Typetable) => {
        const currentFiles = prevInfo[filesKey] || []
        const updatedFiles = typeof newFiles === 'function' ? newFiles(currentFiles) : newFiles

        const updatedInfo: Typetable = {
          ...prevInfo,
          [filesKey]: updatedFiles
        }
        return updatedInfo
      })
    },
    [filesKey, setInfoFu]
  )

  const [activeId, setActiveId] = useState<number | null>(null)
  const myInput = useRef<HTMLInputElement>(null)

  // 修复性能问题：使用useMemo缓存文件ID数组
  const fileIds = useMemo(() => fileList.map(f => f.id), [fileList])

  // 上传多个文件
  const handeUpPhoto = useCallback(
    async (e: React.ChangeEvent<HTMLInputElement>) => {
      if (!e.target.files || e.target.files.length === 0) return

      const files = Array.from(e.target.files)

      if (files.length + fileList.length > maxCount)
        return MessageFu.warning(
          `最多可上传${maxCount}个文件，当前选中${files.length}个文件，还可上传${maxCount - fileList.length}个文件`
        )

      // 逐个上传文件
      for (const file of files) {
        if (size && file.size > size * 1024 * 1024) {
          MessageFu.warning(`文件"${file.name}"超过${size}M限制!`)
          continue
        }
        const typeRes = fileTypeRes(file.name)
        const fd = new FormData()
        fd.append('type', typeRes)
        fd.append('dirCode', dirCode)
        fd.append('isCompress', 'true')
        fd.append('isDb', 'true')
        fd.append('moduleId', info.id + '')
        fd.append('file', file)

        if (fromData) {
          for (const k in fromData) {
            if (fromData[k]) fd.append(k, fromData[k])
          }
        }

        e.target.value = ''

        try {
          const res = await API_upFile(fd, myUrl)
          if (res.code === 0) {
            MessageFu.success(
              `上传成功${files.length > 1 ? `(${files.indexOf(file) + 1}/${files.length})` : ''}`
            )
            setFileList(prev => [res.data, ...prev])
            fileDomInitialFu()
          } else {
            fileDomInitialFu()
          }
        } catch (error) {
          fileDomInitialFu()
        }
      }
    },
    [dirCode, fileList.length, fromData, info.id, maxCount, myUrl, setFileList, size]
  )

  // 修复拖拽逻辑问题：统一使用dnd-kit管理拖拽
  const handleDragStart = useCallback((event: DragStartEvent) => {
    setActiveId(Number(event.active.id))
  }, [])

  // 修复拖拽交换问题：增加类型检查，只有同类型文件才能交换
  const handleDragEnd = useCallback(
    (event: DragEndEvent) => {
      const { active, over } = event
      setActiveId(null)

      if (over && active.id !== over.id) {
        const activeFile = fileList.find(item => item.id === active.id)
        const overFile = fileList.find(item => item.id === over.id)

        // 修复类型检查问题：只有同类型文件才能交换位置
        if (activeFile && overFile && activeFile.type === overFile.type) {
          setFileList(items => {
            const oldIndex = items.findIndex(item => item.id === active.id)
            const newIndex = items.findIndex(item => item.id === over.id)
            return arrayMove(items, oldIndex, newIndex)
          })
        }
      }
    },
    [fileList, setFileList]
  )

  // 列表删除某一个文件
  const delImgListFu = useCallback(
    (id: number) => {
      setFileList(prev => prev.filter(v => v.id !== id))
    },
    [setFileList]
  )

  // 获取当前拖拽的文件
  const activeFile = useMemo(() => {
    return activeId ? fileList.find(file => file.id === activeId) : null
  }, [activeId, fileList])

  // 修复拖拽覆盖层显示问题
  const renderDragOverlay = useCallback(() => {
    if (!activeFile) return null

    if (activeFile.type === 'img') {
      return (
        <div className={classNames('ZTbox1ImgRow', 'dragOverlay')}>
          {activeFile.thumb || activeFile.filePath ? (
            <ImageLazy
              noLook={true}
              width={100}
              height={100}
              src={activeFile.thumb || activeFile.filePath}
            />
          ) : null}
          <div className='ZTbox1ImgRowIcon' style={{ opacity: 0.5 }}>
            <EyeOutlined rev={undefined} />
            <DownloadOutlined rev={undefined} />
          </div>
        </div>
      )
    } else {
      return (
        <div className={classNames('Z3filesRow', 'dragOverlay')}>
          <div className='dragHandle'>
            <MenuOutlined rev={undefined} />
          </div>
          <div className='Z3files1' title={activeFile.fileName}>
            {activeFile.fileName}
          </div>
          <div className='Z3files2'>{/* 拖拽时隐藏操作按钮 */}</div>
        </div>
      )
    }
  }, [activeFile])

  return (
    <div className={styles.Z3upFiles}>
      <input
        id='upInput'
        type='file'
        ref={myInput}
        onChange={handeUpPhoto}
        multiple
        style={{ display: 'none' }}
      />
      <div className='Z3Btn'>
        {!isLook && (
          <Button
            onClick={() => myInput.current?.click()}
            icon={<UploadOutlined rev={undefined} />}
          >
            上传文件
          </Button>
        )}

        <div className='Z3files'>
          <DndContext
            collisionDetection={closestCenter}
            onDragStart={handleDragStart}
            onDragEnd={handleDragEnd}
          >
            <SortableContext items={fileIds} strategy={verticalListSortingStrategy}>
              {fileList.map((file, index) => (
                <SortableFileItem
                  key={file.id}
                  file={file}
                  onDelete={delImgListFu}
                  isLook={isLook}
                  index={index}
                  oneIsCover={oneIsCover}
                />
              ))}
            </SortableContext>
            <DragOverlay>{renderDragOverlay()}</DragOverlay>
          </DndContext>
        </div>

        <div className='fileTit' hidden={isLook}>
          {tips}
          ；支持按住Ctrl键选择多个文件上传；按住鼠标拖动图片 / 拖动附件左侧图标 可调整顺序
          <div
            className={classNames(
              'noUpThumb',
              fileList.length <= 0 && fileCheck ? 'noUpThumbAc' : ''
            )}
          >
            请上传文件!
          </div>
        </div>
      </div>
      {isLook && fileList.length <= 0 ? (
        <div style={{ height: 32, lineHeight: '32px' }}>（空）</div>
      ) : null}
    </div>
  )
}

export default React.memo(Z3upFiles)
