<script setup lang="ts">
import { computed, onMounted, ref } from 'vue'
import { UploadFileInfo } from 'naive-ui'
import { useI18n } from 'vue-i18n'
import { useRouter } from 'vue-router'
import { UploadOne } from '@icon-park/vue-next'
import { fetchUploadKnowledgeDocument } from '@/apis/knowledge'
import { useUserStore } from '@/store/modules/user'

interface Emit {
  (e: 'next', value: number[]): void
}

enum FileItemStatus {
  PENDING = 'pending',
  UPLOADING = 'uploading',
  FINISHED = 'finished',
  REMOVED = 'removed',
  ERROR = 'error',
}

interface FileItem {
  id: string
  name: string
  size: number
  status: FileItemStatus
  kdId: number
  type?: string
}

const { t } = useI18n()

const router = useRouter()

const userStore = useUserStore()

const emit = defineEmits<Emit>()

const uploadFileList = ref<FileItem[]>([])
const isExceedKnowledgeCount = ref(false)

const uploadFileIcon = (type: string) => {
  return `https://gsst-poe-sit.gz.bcebos.com/icon/${type}.svg`
}

const isDisabledNextBtn = computed(() => {
  return (
    uploadFileList.value.length > 0 && uploadFileList.value.every((item) => item.status === FileItemStatus.FINISHED)
  )
})

const uploadFileSize = computed(() => (fileSize: number) => {
  if (fileSize == 0) return '0B'

  const binarySize = 1024
  const sizes = ['B', 'KB', 'MB', 'GB', 'TB']
  const unit = Math.floor(Math.log(fileSize) / Math.log(binarySize))

  return (fileSize / Math.pow(binarySize, unit)).toPrecision(3) + ' ' + sizes[unit]
})

onMounted(async () => {
  await handleGetEquityInfo()
})

async function handleGetEquityInfo() {
  await userStore.fetchUpdateEquityInfo()
}

// 上传文件前限制
function handleLimitUpload(data: { file: UploadFileInfo; fileList: UploadFileInfo[] }) {
  // 上传数量达到上限
  if (isExceedKnowledgeCount.value) {
    return false
  }

  // 获取文件上传时多选的个数
  let uploadKnowledgeCount = 0
  const knowledgeFileList = document.getElementsByClassName('upload-knowledge-file')

  if (knowledgeFileList && knowledgeFileList.length > 0) {
    const knowledgeFile = knowledgeFileList[0].getElementsByTagName('input')
    if (knowledgeFile && knowledgeFile.length > 0 && knowledgeFile[0].files && knowledgeFile[0].files.length > 0) {
      uploadKnowledgeCount = knowledgeFile[0].files.length
    }
  }

  const enableKnowledgeCount = Math.max(
    0,
    userStore.equityInfo.maxKnowledgeCount - userStore.equityInfo.usedKnowledgeCount - uploadFileList.value.length,
  )

  if (userStore.equityInfo.maxKnowledgeCount !== 0 && enableKnowledgeCount < uploadKnowledgeCount) {
    isExceedKnowledgeCount.value = true
    window.$message
      .ctWarning(t('equity_module.documents_uploaded_exceeds_tip', { count: enableKnowledgeCount }), '')
      .then(() => {
        router.push({ name: 'Equity' })
      })
      .catch(() => {})

    return false
  }

  const allowTypeList = ['md', 'doc', 'docx', 'pdf', 'txt']

  const fileType = (data.file.file && data.file.file?.name.split('.')?.pop()?.toLowerCase()) || ''

  if (fileType && !allowTypeList.includes(fileType)) {
    window.$message.error(
      t('personal_space_module.knowledge_module.upload_document_module.upload_format_error_message'),
    )
    return false
  }

  if (data.file.file && data.file.file?.size === 0) {
    window.$message.error(
      t('personal_space_module.knowledge_module.upload_document_module.empty_document_content_message'),
    )
    const fileData = {
      id: data.file.id,
      name: data.file.name,
      status: FileItemStatus.ERROR,
      size: data.file.file?.size || 0,
      type: fileType,
      kdId: 0,
    }

    uploadFileList.value.push(fileData)
    return false
  }

  if (data.file.file && data.file.file?.size > 10 * 1024 * 1024) {
    window.$message.error(t('personal_space_module.knowledge_module.upload_document_module.upload_size_error_message'))
    const fileData = {
      id: data.file.id,
      name: data.file.name,
      status: FileItemStatus.ERROR,
      size: data.file.file?.size || 0,
      type: fileType,
      kdId: 0,
    }

    uploadFileList.value.push(fileData)
    return false
  }

  return true
}

// 上传文件
async function handleUpload(file: any) {
  const formData = new FormData()
  formData.append('documentFiles', file.file.file)

  const fileData = {
    id: file.file.id,
    name: file.file.name,
    status: FileItemStatus.UPLOADING,
    size: file.file?.file?.size || 0,
    type: file.file?.name.split('.')?.pop()?.toLowerCase(),
    kdId: 0,
  }

  if (uploadFileList.value.length < 5) {
    await uploadFileList.value.push(fileData)

    fetchUploadKnowledgeDocument<{ kdId: number }[]>(formData)
      .then((res) => {
        if (res.code === 0) {
          uploadFileList.value.forEach((fileItem) => {
            if (fileItem.id === file.file.id) {
              fileItem.status = FileItemStatus.FINISHED
              fileItem.kdId = res.data?.[0]?.kdId
            }
          })
        }
      })
      .catch(() => {
        uploadFileList.value.forEach((fileItem) => {
          if (fileItem.id === file.file.id) {
            fileItem.status = FileItemStatus.ERROR
          }
        })
      })
  }
}

// 拖拽文件
function handleDropFile(e: DragEvent) {
  const files = e.dataTransfer?.files as FileList
  const file = files[0]

  isExceedKnowledgeCount.value = false
  const dropKnowledgeCount = files.length
  const enableKnowledgeCount = Math.max(
    0,
    userStore.equityInfo.maxKnowledgeCount - userStore.equityInfo.usedKnowledgeCount - uploadFileList.value.length,
  )

  if (userStore.equityInfo.maxKnowledgeCount !== 0 && enableKnowledgeCount < dropKnowledgeCount) {
    isExceedKnowledgeCount.value = true

    window.$message
      .ctWarning(t('equity_module.documents_uploaded_exceeds_tip', { count: enableKnowledgeCount }), '')
      .then(() => {
        router.push({ name: 'Equity' })
      })
      .catch(() => {})

    return
  }

  const allowTypeList = ['md', 'doc', 'docx', 'pdf', 'txt']

  if (file && file.name) {
    const fileType = file.name.split('.')?.pop()?.toLowerCase() || ''
    if (!allowTypeList.includes(fileType)) {
      window.$message.error(
        t('personal_space_module.knowledge_module.upload_document_module.upload_format_error_message'),
      )
      return false
    }
  }
}

function handleRemoveFile(id: string) {
  uploadFileList.value = uploadFileList.value.filter((item) => item.id !== id)
}

function handleNextStep() {
  const kdIds = uploadFileList.value.map((item) => item.kdId)

  emit('next', kdIds)
}
</script>

<template>
  <div class="w-full">
    <NUpload
      multiple
      directory-dnd
      :show-file-list="false"
      :disabled="uploadFileList.length >= 5"
      class="upload-knowledge-file"
      accept=".doc, .pdf, .docx, .txt, .md"
      @before-upload="handleLimitUpload"
      @change="handleUpload"
      @drop="handleDropFile"
    >
      <NUploadDragger @click="isExceedKnowledgeCount = false">
        <div class="mb-3 flex justify-center">
          <UploadOne theme="outline" size="36" fill="#333" />
        </div>
        <NText class="text-base">
          {{ t('personal_space_module.knowledge_module.upload_document_module.upload_action_tip_message') }}
        </NText>
        <p class="text-gray-font-color mt-3 text-sm">
          {{ t('personal_space_module.knowledge_module.upload_document_module.upload_limit_tip_message') }}
        </p>
      </NUploadDragger>
    </NUpload>

    <div class="mt-[18px]">
      <ul class="grid grid-cols-2 gap-4">
        <li
          v-for="uploadFileItem in uploadFileList"
          :key="uploadFileItem.id"
          class="group relative h-[92px] w-full overflow-hidden rounded-[10px] border bg-white p-6"
          :class="uploadFileItem.status === 'error' ? 'border-error-font-color' : 'border-transparent'"
        >
          <div class="flex items-center justify-between">
            <div class="flex items-center">
              <img :src="uploadFileIcon(uploadFileItem.type!)" class="h-9 w-9" />

              <div class="mx-4 flex flex-col">
                <NPopover trigger="hover">
                  <template #trigger>
                    <span class="text-font-color mb-2 line-clamp-1 select-none break-all text-base leading-4">
                      {{ uploadFileItem.name }}
                    </span>
                  </template>
                  <span>{{ uploadFileItem.name }}</span>
                </NPopover>

                <div
                  v-if="uploadFileItem.status === FileItemStatus.FINISHED"
                  class="text-gray-font-color line-clamp-1 select-none break-all"
                >
                  <span class="inline-block group-hover:hidden">{{ uploadFileSize(uploadFileItem.size) }}</span>
                  <span class="hidden group-hover:inline-block">{{ t('common_module.upload_success_message') }}</span>
                </div>

                <div
                  v-else-if="uploadFileItem.status === FileItemStatus.UPLOADING"
                  class="text-gray-font-color line-clamp-1 select-none break-all"
                >
                  <span>{{ t('common_module.uploading') }}</span>
                </div>

                <span v-else class="text-error-font-color line-clamp-1 select-none break-all">
                  {{ t('personal_space_module.knowledge_module.upload_document_module.upload_error_message') }}
                </span>
              </div>
            </div>

            <div
              v-show="[FileItemStatus.FINISHED, FileItemStatus.ERROR].includes(uploadFileItem.status)"
              class="hidden group-hover:block"
            >
              <NPopover trigger="hover">
                <template #trigger>
                  <i
                    class="iconfont icon-close cursor-pointer text-base outline-none hover:opacity-80"
                    :class="
                      uploadFileItem.status === FileItemStatus.ERROR ? 'text-error-font-color' : 'text-font-color'
                    "
                    @click="handleRemoveFile(uploadFileItem.id)"
                  />
                </template>
                <span>{{ t('common_module.delete') }}</span>
              </NPopover>
            </div>
          </div>

          <div
            v-show="[FileItemStatus.UPLOADING].includes(uploadFileItem.status)"
            class="animate-training absolute left-0 top-[-1px] h-[92px] w-full rounded-[10px] bg-gradient-to-r from-transparent via-[#9EA0FF] to-transparent"
          />
        </li>
      </ul>
    </div>

    <div class="mt-14 flex justify-end">
      <NButton type="primary" :disabled="!isDisabledNextBtn" :bordered="false" @click="handleNextStep">
        {{ t('common_module.next_btn_text') }}
      </NButton>
    </div>
  </div>
</template>
