<template>
  <div class="step-device-category h-full flex flex-col">
    <div class="flex-1 overflow-y-auto">
      <el-tabs
        v-if="Object.keys(modelValue).length > 0"
        v-model="activeTab"
        type="card"
        class="h-full flex flex-col"
      >
        <el-tab-pane
          v-for="(categoriesMap, channelType) in modelValue"
          :key="channelType"
          :label="
            Object.entries(ChannelEnum).find(([key, val]) => val === channelType)?.[1]
          "
          :name="channelType"
        >
          <el-scrollbar>
            <div class="grid grid-cols-[repeat(auto-fill,minmax(300px,1fr))] gap-4 p-4">
              <div
                class="bg-white rounded-xl shadow-sm p-12 border-2 border-dashed border-gray-200 hover:border-blue-400 transition-all duration-300 cursor-pointer flex items-center justify-center min-h-[200px]"
                @click="handleAdd"
              >
                <div class="flex flex-col items-center gap-3">
                  <el-icon :size="48" class="text-gray-400">
                    <Plus />
                  </el-icon>
                  <span class="text-base font-medium text-gray-600">新增设备类别</span>
                </div>
              </div>
              <div
                v-for="{ fileName, name: categoryName, status } in categoriesMap"
                :key="fileName"
                class="bg-white rounded-xl shadow-sm p-12 border border-gray-100 hover:shadow-lg transition-all duration-300"
              >
                <div class="flex justify-between items-start mb-3">
                  <div class="flex-1 min-w-0 flex items-center justify-between">
                    <h3
                      class="font-bold text-lg text-gray-900 truncate"
                      :title="categoryName as string"
                    >
                      类别名称：{{ categoryName }}
                    </h3>
                    <el-tag
                      v-if="!!status"
                      size="small"
                      type="success"
                      effect="light"
                      class="rounded-md"
                    >
                      已上传
                    </el-tag>
                    <el-tag
                      v-else
                      size="small"
                      type="info"
                      effect="light"
                      class="rounded-md"
                    >
                      未上传
                    </el-tag>
                  </div>
                </div>
                <div>
                  <div class="space-y-2 mb-3">
                    <div class="text-sm">
                      <div class="flex items-center justify-between">
                        <span class="text-gray-500 whitespace-nowrap">点表文件：</span>
                        <el-tooltip
                          effect="dark"
                          :content="fileName"
                          placement="top"
                          :disabled="!fileName"
                        >
                          <span class="text-gray-900 font-medium truncate max-w-[170px]">
                            {{ fileName || '-' }}
                          </span>
                        </el-tooltip>
                        <div
                          class="ml-2"
                          v-if="!!status"
                          @click.stop="handleDownload(categoryName as string)"
                        >
                          <el-button type="primary" :icon="Download" link>下载</el-button>
                        </div>
                      </div>
                    </div>
                  </div>
                  <div class="upload-area relative">
                    <div
                      v-if="uploadingStates[fileName]"
                      class="absolute inset-0 z-10 bg-white/90 flex items-center justify-center rounded-lg"
                    >
                      <el-button
                        type="danger"
                        size="small"
                        @click="handleCancelUpload(fileName as string)"
                      >
                        取消上传
                      </el-button>
                    </div>
                    <el-upload
                      :ref="(el) => setUploadRef(el, fileName as string)"
                      class="upload-demo"
                      drag
                      :auto-upload="false"
                      :limit="1"
                      :show-file-list="false"
                      :disabled="uploadingStates[fileName]"
                      :on-change="
                        (file: any) => handleFileChange(file, fileName as string, categoryName)
                      "
                    >
                      <el-icon class="el-icon--upload !text-3xl !mb-2 !text-gray-400"
                        ><upload-filled
                      /></el-icon>
                      <div class="el-upload__text text-xs text-gray-500">
                        拖拽文件或<em class="text-blue-500 not-italic cursor-pointer"
                          >点击/{{ !!status ? '重新' : '' }}上传</em
                        >
                      </div>
                    </el-upload>
                  </div>
                </div>
              </div>
            </div>
          </el-scrollbar>
        </el-tab-pane>
      </el-tabs>
      <div v-if="Object.keys(modelValue).length === 0">
        <div
          class="bg-white rounded-xl w-340 shadow-sm p-12 border-2 border-dashed border-gray-200 hover:border-blue-400 transition-all duration-300 cursor-pointer flex items-center justify-center min-h-[200px]"
          @click="handleAdd"
        >
          <div class="flex flex-col items-center gap-3">
            <el-icon :size="48" class="text-gray-400">
              <Plus />
            </el-icon>
            <span class="text-base font-medium text-gray-600">新增设备类别</span>
          </div>
        </div>
        <el-empty description="暂无设备类别，请点击上方按钮添加" />
      </div>
    </div>

    <el-dialog
      v-model="dialogVisible"
      :title="'新增设备类别'"
      width="500px"
      append-to-body
      destroy-on-close
    >
      <el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
        <el-form-item label="类别名称：" prop="pointName">
          <el-input v-model="form.pointName" placeholder="请输入类别名称" />
        </el-form-item>
      </el-form>
      <el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
        <el-form-item label="通道类型：" prop="groupName">
          <el-select v-model="form.groupName" placeholder="请选择通道类型">
            <el-option
              v-for="[key, val] in Object.entries(ChannelEnum)"
              :key="key"
              :label="val"
              :value="val"
            />
          </el-select>
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="dialogVisible = false">取消</el-button>
          <el-button type="primary" @click="handleSave">确定</el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, computed, watch } from 'vue'
import { useRoute } from 'vue-router'
import { UploadFilled, Plus, Download } from '@element-plus/icons-vue'
import type { IDeviceCategoryList, IDeviceCategoryOV } from '@/api/module/device/index.d'
import type { FormInstance, FormRules, UploadFile } from 'element-plus'
import { ElMessage, ElMessageBox } from 'element-plus'
import {
  createDeviceType,
  uploadDeviceTypeFile,
  downloadDeviceTypeFile,
} from '@/api/module/device/category'
import { ChannelEnum } from '@/api/module/channel/index'
import type { IChannelOV } from '@/api/module/channel/index.d'
import { validateName } from '@/utils/validate'

const props = defineProps<{
  modelValue: IDeviceCategoryList
  channels: IChannelOV
}>()

const emit = defineEmits<{
  (e: 'update:modelValue', value: IDeviceCategoryList): void
  (e: 'on-load-device-categoty'): void
}>()
const route = useRoute()
const projectName = computed(() => route.query.name as string)

const dialogVisible = ref(false)
const formRef = ref<FormInstance>()

const uploadControllers = reactive<{ [key: string]: AbortController }>({})
const uploadingStates = reactive<{ [key: string]: boolean }>({})

const activeTab = ref<string>('modbus')

watch(
  () => props.modelValue,
  val => {
    if (
      val &&
      Object.keys(val).length > 0 &&
      !Object.keys(val).includes(activeTab.value)
    ) {
      activeTab.value = Object.keys(val)[0]
    }
  },
  { immediate: true, deep: true },
)

const form = reactive<IDeviceCategoryOV>({
  pointName: '',
  fileName: '',
  groupName: '',
})

const rules = reactive<FormRules>({
  pointName: [
    { required: true, message: '请输入类别名称', trigger: 'blur' },
    {
      validator: (rule: any, value: any, callback: any) => {
        const error = validateName(value)
        if (error) {
          callback(new Error(error))
        } else {
          callback()
        }
      },
      trigger: 'blur',
    },
  ],
  groupName: [{ required: true, message: '请输入通道类型', trigger: 'blur' }],
})

const handleAdd = () => {
  form.pointName = ''
  form.fileName = ''
  form.groupName = ''
  dialogVisible.value = true
}

const handleSave = async () => {
  if (!formRef.value) return
  await formRef.value.validate(async valid => {
    if (valid) {
      await addDeviceType()
    }
  })
}

async function addDeviceType() {
  const res = await createDeviceType({
    pointName: form.pointName,
    projectName: projectName.value,
    groupName: form.groupName,
  })
  if (res.code !== 0) {
    ElMessage.error(res?.msg || '添加失败')
    dialogVisible.value = false
    return
  }
  emit('on-load-device-categoty')
  dialogVisible.value = false
}

const uploadRefs = ref<Record<string, any>>({})
const setUploadRef = (el: any, key: string) => {
  if (el) {
    uploadRefs.value[key] = el
  }
}

const handleFileChange = async (
  file: UploadFile,
  fileName: string,
  categoryName: string,
) => {
  if (!file.raw) return
  const controller = new AbortController()
  uploadControllers[fileName] = controller
  uploadingStates[fileName] = true

  try {
    const res = await uploadDeviceTypeFile(
      {
        file: file.raw,
        projectName: projectName.value,
        fileName: fileName,
        pointName: categoryName,
      },
      controller,
    )
    if (res) {
      if (res.code === 0) {
        ElMessage.success('上传成功')
        emit('on-load-device-categoty')
      } else if (res.code === 10001) {
        ElMessage.success('取消成功')
      } else {
        ElMessage.error(res.msg || '上传失败')
      }
    }
  } finally {
    delete uploadControllers[fileName]
    uploadingStates[fileName] = false
    uploadRefs.value[fileName]?.clearFiles()
  }
}

const handleCancelUpload = (fileName: string) => {
  const controller = uploadControllers[fileName]
  if (controller) {
    controller.abort()
    delete uploadControllers[fileName]
    uploadingStates[fileName] = false
  }
}

// Check if there are any uploading files
const hasUploadingFiles = () => {
  return Object.values(uploadingStates).some(state => state === true)
}

// Cancel all uploads
const cancelAllUploads = () => {
  Object.keys(uploadControllers).forEach(fileName => {
    handleCancelUpload(fileName)
  })
}

async function handleDownload(pointName: string) {
  try {
    const res = await fetch(
      `/remoteServer/admin-api/project/point/download-excel?projectName=${projectName.value}&pointName=${pointName}`,
    )
    debugger
    // 检查响应是否成功
    if (!res.ok) {
      throw new Error('Network response was not ok')
    }
    const blob = await res.blob()
    const link = document.createElement('a')
    link.style.display = 'none'
    link.href = URL.createObjectURL(blob)
    link.download = `${pointName}.xlsx`
    document.body.appendChild(link)
    link.click()
    document.body.removeChild(link)
    URL.revokeObjectURL(link.href)
  } catch (error) {
    ElMessage.error('下载出现错误')
  }
}

// Check before leaving step
const checkBeforeLeave = async (): Promise<boolean> => {
  if (!hasUploadingFiles()) {
    return true
  }

  return new Promise(resolve => {
    ElMessageBox.confirm(
      '当前有文件正在上传，离开将取消所有上传任务，是否确定离开？',
      '提示',
      {
        confirmButtonText: '确定离开',
        cancelButtonText: '取消',
        type: 'warning',
      },
    )
      .then(() => {
        cancelAllUploads()
        resolve(true)
      })
      .catch(() => {
        resolve(false)
      })
  })
}

defineExpose({
  checkBeforeLeave,
})
</script>

<style scoped>
:deep(.el-tabs__content) {
  flex: 1;
  overflow: hidden;
  height: 0;
}

:deep(.el-tab-pane) {
  height: 100%;
}

:deep(.el-scrollbar__view) {
  height: 100%;
}

.upload-demo {
  width: 100%;
}

:deep(.el-upload-dragger) {
  padding: 20px;
}

:deep(.el-icon--upload) {
  font-size: 40px;
  color: #409eff;
  margin-bottom: 8px;
}

:deep(.el-upload__text) {
  font-size: 14px;
  line-height: 1.5;
}
</style>
