import { getLocalFileChunk, uploadLocalFile } from '@/api/base'

interface FileItem {
  file: File
  url: string
  name: string
  progress: number
  abortController: AbortController
}

interface UploadOptions {
  multiple?: boolean
  autoUpload?: boolean
  onUploadStarted?: (file: FileItem) => void
  onUploadSucceed?: (file: FileItem) => void
  onUploadFailed?: (file: FileItem, error: any) => void
  onUploadProgress?: (file: FileItem, progress: number) => void
  onUploadEnd?: () => void
}

export function useUpload(options: UploadOptions = {}) {
  options = Object.assign({ autoUpload: true, multiple: false }, options)
  const files = ref<FileItem[]>([])
  const uploading = ref(false)

  function addFile(file: File) {
    // 检查文件是否已经在队列中
    const existingFileIndex = files.value.findIndex((f) => f.name === file.name)
    // 如果文件已经在队列中，并且上传已经开始，则直接返回
    if (existingFileIndex !== -1 && files.value[existingFileIndex].progress > 0) return

    if (!options.multiple) stopUpload()
    const abortController = new AbortController()
    files.value.push({ url: '', name: file.name, file, progress: 0, abortController })
    if (options.autoUpload && !uploading.value) startUpload()
  }

  async function startUpload() {
    uploading.value = true
    for (const file of files.value) {
      if (file.progress === 0) {
        // 只处理尚未开始上传的文件
        try {
          options?.onUploadStarted?.(file)
          await uploadFile(file)
          options?.onUploadSucceed?.(file)
        } catch (error) {
          options?.onUploadFailed?.(file, error)
        }
      }
    }
    uploading.value = false
    options?.onUploadEnd?.()
  }

  async function uploadFile(file: FileItem) {
    const {
      data: { detail },
    } = await getLocalFileChunk({ file_name: file.file.name, file_size: file.file.size })
    const fileName = detail.file_name
    const chunkSize = detail.chunk_size
    const totalChunks = Math.ceil(file.file.size / chunkSize)

    for (let chunkIndex = 0; chunkIndex < totalChunks; chunkIndex++) {
      const chunk = file.file.slice(chunkIndex * chunkSize, (chunkIndex + 1) * chunkSize)
      await uploadChunk({ file, chunk, chunkIndex, fileName, totalChunks })
    }
  }

  async function uploadChunk({
    file,
    chunk,
    chunkIndex,
    fileName,
    totalChunks,
  }: {
    file: FileItem
    chunk: Blob
    chunkIndex: number
    fileName: string
    totalChunks: number
  }) {
    const {
      data: { detail },
    } = await uploadLocalFile(
      { file_name: fileName, file: chunk, now_package_num: chunkIndex + 1, total_package_num: totalChunks },
      {
        signal: file.abortController.signal,
        onUploadProgress(event: ProgressEvent) {
          updateProgress({ file, event, chunkIndex, totalChunks })
        },
      },
    )
    file.url = detail.uri
  }

  function updateProgress({
    event,
    chunkIndex,
    totalChunks,
    file,
  }: {
    file: FileItem
    event: ProgressEvent
    chunkIndex: number
    totalChunks: number
  }) {
    const totalSize = event.total * totalChunks
    const loadedSize = event.loaded + chunkIndex * event.total
    const progressPercent = (loadedSize / totalSize) * 100
    file.progress = parseFloat(progressPercent.toFixed(2))
    options?.onUploadProgress?.(file, file.progress)
  }

  function cancelUpload(file: FileItem) {
    file.abortController.abort()
    files.value = files.value.filter((item) => item.name !== file.name)
  }

  function stopUpload() {
    files.value.forEach(cancelUpload) // 停止所有文件的上传
    files.value.length = 0
    uploading.value = false // 更新上传状态
  }

  return { files, uploading, addFile, startUpload, cancelUpload, stopUpload }
}
