<template>
  <div>
    <el-dialog :title="title" :visible.sync="isOpen" width="500px" append-to-body @close="cancel"
               :close-on-click-modal="false"
    >
      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
        <el-form-item label="镜像名称" prop="mirrorName">
          <el-input v-model="form.mirrorName" maxlength="100" placeholder="请输入镜像名称"/>
        </el-form-item>
        <el-form-item label="镜像版本" prop="mirrorVersion">
          <el-input v-model="form.mirrorVersion" placeholder="请输入镜像名称"/>
        </el-form-item>
        <el-form-item label="所属模型" prop="ownModel">
          <el-select v-model="form.ownModel" placeholder="请选择所属模型" clearable style="width: 100%">
            <el-option v-for="dict in modelList" :key="dict.id" :label="dict.modelName +' - '+dict.modelVersion"
                       :value="dict.id"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="运行环境" prop="runEnvironment">
          <el-select v-model="form.runEnvironment" placeholder="请选择运行环境" clearable style="width: 100%">
            <el-option v-for="dict in runEnvironmentList" :key="dict.value" :label="dict.label"
                       :value="dict.value"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="模型框架" prop="modelFrame">
          <el-select v-model="form.modelFrame" placeholder="请选择模型框架" clearable style="width: 100%">
            <el-option v-for="dict in dict.type.ai_frame_type" :key="dict.value" :label="dict.label"
                       :value="dict.value"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="语言" prop="language">
          <el-select v-model="form.language" placeholder="请选择语言" clearable style="width: 100%">
            <el-option v-for="dict in languageList" :key="dict.value" :label="dict.label"
                       :value="dict.value"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="镜像文件" prop="modelFileName">
          <div class="custom-upload">
            <input type="file" ref="modelInput" style="display: none" @change="handleFileChange('modelFile', $event)"
                   accept=".zip"
            />
            <el-button size="mini" type="text" v-if="!form.modelFileName" @click="triggerFileInput('modelInput')">选择文件
            </el-button>
            <span style="cursor: pointer;" @click="triggerFileInput('modelInput')" v-if="form.modelFileName"
            >{{ form.modelFileName }}</span>
            <el-progress v-if="uploading" :percentage="uploadProgress.modelFile"/>
          </div>
        </el-form-item>
        <el-form-item label="接口文档" prop="manualFileName">
          <div class="custom-upload">
            <input type="file" ref="manualInput" style="display: none"
                   @change="handleFileChange('manualFile', $event)" accept=".doc,.docx,.pdf"
            />
            <el-button size="mini" type="text" v-if="!form.manualFileName" @click="triggerFileInput('manualInput')">
              选择文件
            </el-button>
            <span style="cursor: pointer;" @click="triggerFileInput('manualInput')" v-if="form.manualFileName"
            >{{ form.manualFileName }}<i></i></span>
            <el-progress v-if="uploading" :percentage="uploadProgress.manualFile"/>
          </div>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="submitForm">确 定</el-button>
        <el-button @click="cancel">取 消</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import { getManager, addManager, updateManager, uploadFile, listAll } from '@/api/dataCenter/mirror'
import { datasetList } from '@/api/dataCenter/dataSet'
import { generateUUID } from '../../../../utils/configure'

export default {
  dicts: ['ai_annotate_type', 'ai_frame_type'],
  props: {
    open: { type: Boolean, required: true },
    getList: { type: Function, required: true },
    title: { type: String, required: true },
    mirrorId: { type: [Number, null], default: 0 }
  },
  computed: {
    isOpen: {
      get() {
        return this.open
      },
      set(value) {
        this.$emit('dialog-cancel')
      }
    }
  },
  data() {
    return {
      runEnvironmentList: [{
        value: '0',
        label: 'CPU'
      },
        {
          value: '1',
          label: 'GPU'
        }],
      languageList: [
        { 'value': '0', 'label': 'Java' },
        { 'value': '1', 'label': 'Python' },
        { 'value': '2', 'label': 'JavaScript (Node.js)' },
        { 'value': '3', 'label': 'PHP' },
        { 'value': '4', 'label': 'C# (.NET)' },
        { 'value': '5', 'label': 'Ruby' },
        { 'value': '6', 'label': 'Go (Golang)' },
        { 'value': '7', 'label': 'C/C++' },
        { 'value': '8', 'label': 'Kotlin' },
        { 'value': '9', 'label': 'Rust' },
        { 'value': '10', 'label': 'Scala' },
        { 'value': '11', 'label': 'Perl' },
        { 'value': '12', 'label': 'Swift' },
        { 'value': '13', 'label': 'Elixir' }
      ],
      modelList: [],
      uploadProgress: { modelFile: 0, manualFile: 0 },
      uploading: false,
      chunkSize: 1024 * 1024 * 20, // 20MB
      form: { modelFile: null, manualFile: null, modelFileName: '', manualFileName: '' },
      rules: {
        mirrorName: [{ required: true, message: '镜像名称不能为空', trigger: 'blur' }],
        mirrorVersion: [{
          required: true,
          message: '版本号不能为空',
          trigger: 'blur'
        }, { pattern: /^V\d{1,3}(\.\d{1,3}){2}$/, message: '版本名称式不正确，应为 VX.Y.Z 格式', trigger: 'blur' }],
        runEnvironment: [{ required: true, message: '请选择运行环境', trigger: 'blur' }],
        language: [{ required: true, message: '请选择语言', trigger: 'blur' }],
        modelFrame: [{ required: true, message: '请选择模型框架', trigger: 'blur' }],
        modelFileName: [{ required: true, message: '请上传镜像文件', trigger: 'blur' }],
        manualFileName: [{ required: true, message: '请上传接口文档', trigger: 'blur' }]
      },
      currentUpload: { modelFile: null, manualFile: null } // 为每个文件设置独立的上传任务
    }
  },
  watch: {
    isOpen(newVal) {
      if (newVal) {
        console.log(this.mirrorId)
        if (this.mirrorId) {
          getManager(this.mirrorId).then(response => {
            this.form = response.data
          })
          listAll().then(response => {
            this.modelList = response.data
          })
        }
      }
    }
  },
  methods: {
    triggerFileInput(refName) {
      this.$refs[refName].click()
    },
    handleFileChange(field, event) {
      const file = event.target.files[0]
      if (file) {
        this.form[field] = file
        this.form[`${field}Name`] = file.name
      }
    },
    resetField(field) {
      this.form[field] = null
      this.form[`${field}Name`] = ''
      this.$refs[field].value = ''  // 重置文件选择
    },
    uploadChunks(file, field, uuid) {
      return new Promise((resolve, reject) => {
        // 文件为空时直接返回
        if (!file || file.size === 0) {
          resolve()
        }
        const totalChunks = Math.ceil(file.size / this.chunkSize)
        let currentChunk = 0
        this.uploading = true // 标记正在上传
        const controller = new AbortController() // 新增AbortController
        const signal = controller.signal // 获取 signal 用于中止请求

        const uploadNextChunk = () => {
          if (this.uploading === false) { // 如果上传已经取消，退出
            reject('Upload canceled')
            return
          }
          const start = currentChunk * this.chunkSize
          const end = Math.min(file.size, start + this.chunkSize)
          const chunk = file.slice(start, end)
          const formData = new FormData()
          formData.append('file', chunk)
          formData.append('fileName', uuid + `.${file.name.split('.').pop().toLowerCase()}`)
          formData.append('chunk', currentChunk + 1)
          formData.append('totalChunks', totalChunks)
          uploadFile(formData, { signal })  // 在上传请求中传入 signal 用于中止
            .then(res => {
              currentChunk++
              // 更新进度
              this.uploadProgress[field] = Math.floor((currentChunk / totalChunks) * 100)
              if (currentChunk < totalChunks) {
                uploadNextChunk()
              } else {
                if (field === 'modelFile') {
                  this.form.mirrorPath = res.data.fileUrl
                }
                if (field === 'manualFile') {
                  this.form.documentPath = res.data.fileUrl
                }
                resolve() // 上传完成，返回成功
              }
            })
            .catch(error => {
              if (error.name === 'AbortError') {
                console.log('Upload was aborted')
              }
              reject(error) // 上传失败，返回失败
              this.$message.error('上传失败')
            })
        }

        uploadNextChunk()
        // 将当前上传任务保存到 currentUpload 中
        this.currentUpload[field] = {
          abort: () => controller.abort() // 提供 abort 方法来中止上传
        }

        return this.currentUpload[field] // 返回当前上传任务
      })
    },
    submitForm() {
      this.$refs.form.validate(valid => {
        if (valid) {
          // 上传文件后再调用新增或修改操作
          // 独立上传每个文件，并确保只有所有文件上传成功后才提交表单
          Promise.all([
            this.uploadChunks(this.form.modelFile, 'modelFile', generateUUID()),
            this.uploadChunks(this.form.manualFile, 'manualFile', generateUUID())
          ]).then(() => {
            this.uploading = false
            const action = this.form.id ? updateManager : addManager
            action(this.form)
              .then(() => {
                this.$message.success(this.form.id ? '修改成功' : '新增成功')
                this.cancel()
                this.getList()
              })
          })
            .catch(() => {
              this.$message.error('文件上传失败，无法提交')
            })
        }
      })
    },
    cancel() {
      this.isOpen = false
      this.uploading = false
      // 取消当前文件的上传任务
      if (this.currentUpload.modelFile && this.currentUpload.modelFile.abort) {
        this.currentUpload.modelFile.abort()
      }
      if (this.currentUpload.manualFile && this.currentUpload.manualFile.abort) {
        this.currentUpload.manualFile.abort()
      }
      this.resetForm()
    },
    resetForm() {
      this.resetField('modelInput')
      this.resetField('manualInput')
      this.uploading = false
      this.uploadProgress = { modelFile: 0, manualFile: 0 }
      this.form = { modelFile: null, manualFile: null, modelFileName: '', manualFileName: '' }
    }
  }
}
</script>

<style scoped lang="scss"></style>
