import { InboxOutlined } from '@ant-design/icons'
import { message, Modal, Select, Upload } from 'antd'
import type { UploadFile, UploadProps } from 'antd'
import { useEffect, useMemo, useState } from 'react'
import type { FileCategory, FileUploadConfig } from '../../api'
import { flattenCategoryOptions } from '../../utils/fileTree'

const { Dragger } = Upload

interface UploadResult {
  succeeded: number
  failed: number
}

interface FileUploadModalProps {
  open: boolean
  categories: FileCategory[]
  config: FileUploadConfig
  initialCategoryId: string | null
  onClose: () => void
  onUpload: (files: File[], categoryId: string | null) => Promise<UploadResult>
}

export default function FileUploadModal({
  open,
  categories,
  config,
  initialCategoryId,
  onClose,
  onUpload,
}: FileUploadModalProps) {
  const [targetCategoryId, setTargetCategoryId] = useState<string | undefined>()
  const [fileList, setFileList] = useState<UploadFile[]>([])
  const [uploading, setUploading] = useState(false)

  useEffect(() => {
    if (open) {
      setTargetCategoryId(initialCategoryId ?? undefined)
      setFileList([])
    }
  }, [initialCategoryId, open])

  const options = useMemo(() => flattenCategoryOptions(categories), [categories])
  const accept = config.allowed_extensions.map((extension) => `.${extension}`).join(',')

  const uploadProps: UploadProps = {
    multiple: true,
    accept: accept || undefined,
    fileList,
    customRequest: () => undefined,
    beforeUpload: (file) => {
      const maxBytes = config.max_upload_size_mb * 1024 * 1024
      if (file.size > maxBytes) {
        message.error(`${file.name} 超过 ${config.max_upload_size_mb}MB 限制`)
        return Upload.LIST_IGNORE
      }
      return true
    },
    onChange: ({ fileList: nextFileList }) => setFileList(nextFileList),
    onRemove: (file) => {
      setFileList((current) => current.filter((item) => item.uid !== file.uid))
      return true
    },
  }

  const handleUpload = async () => {
    const files = fileList.flatMap((item) => item.originFileObj ? [item.originFileObj] : [])
    if (files.length === 0) return

    setUploading(true)
    try {
      const result = await onUpload(files, targetCategoryId ?? null)
      if (result.succeeded > 0 && result.failed === 0) {
        message.success(`成功上传 ${result.succeeded} 个文件`)
      } else if (result.succeeded > 0) {
        message.warning(`成功 ${result.succeeded} 个，失败 ${result.failed} 个`)
      } else {
        message.error('上传失败，请检查文件格式和大小')
      }
      onClose()
    } finally {
      setUploading(false)
    }
  }

  const formats = config.allowed_extensions.length > 0
    ? config.allowed_extensions.map((extension) => `.${extension}`).join(' ')
    : '正在读取支持格式'

  return (
    <Modal
      title="上传文件"
      open={open}
      onCancel={onClose}
      onOk={() => void handleUpload()}
      okText="开始上传"
      confirmLoading={uploading}
      okButtonProps={{ disabled: fileList.length === 0 }}
      width={520}
      destroyOnHidden
    >
      <div className="files-upload-category">
        <span>目标分类：</span>
        <Select
          allowClear
          placeholder="选择分类（可选）"
          value={targetCategoryId}
          onChange={setTargetCategoryId}
          options={options}
        />
      </div>
      <Dragger {...uploadProps}>
        <p className="ant-upload-drag-icon"><InboxOutlined /></p>
        <p className="ant-upload-text">点击或拖拽文件到此区域上传</p>
        <p className="ant-upload-hint">
          {formats}，单文件最大 {config.max_upload_size_mb}MB
        </p>
      </Dragger>
    </Modal>
  )
}
