<template>
  <el-dialog
    v-model="visible"
    :title="title"
    :width="width"
    :close-on-click-modal="false"
    :close-on-press-escape="!uploading"
    @closed="handleClosed"
  >
    <div class="import-dialog-content">
      <!-- 下载模板 -->
      <div v-if="templateUrl" class="template-section">
        <el-alert
          title="请先下载导入模板，按照模板格式填写数据"
          type="info"
          :closable="false"
          show-icon
        >
          <template #default>
            <el-button type="primary" link @click="handleDownloadTemplate">
              <el-icon><Download /></el-icon>
              下载模板
            </el-button>
          </template>
        </el-alert>
      </div>

      <!-- 文件上传 -->
      <el-upload
        ref="uploadRef"
        class="upload-area"
        drag
        :action="uploadAction"
        :before-upload="handleBeforeUpload"
        :on-success="handleUploadSuccess"
        :on-error="handleUploadError"
        :on-progress="handleUploadProgress"
        :file-list="fileList"
        :limit="1"
        :accept="accept"
        :auto-upload="false"
        :disabled="uploading"
      >
        <el-icon class="upload-icon"><UploadFilled /></el-icon>
        <div class="upload-text">
          <div>将文件拖到此处，或<em>点击上传</em></div>
          <div class="upload-tip">只能上传 {{ acceptText }} 文件，且不超过 {{ maxSizeMB }}MB</div>
        </div>
      </el-upload>

      <!-- 上传进度 -->
      <div v-if="uploading" class="upload-progress">
        <el-progress :percentage="uploadProgress" />
        <p>正在上传中，请稍候...</p>
      </div>

      <!-- 导入结果 -->
      <div v-if="importResult" class="import-result">
        <el-alert
          :title="importResult.message"
          :type="importResult.success ? 'success' : 'error'"
          :closable="false"
          show-icon
        >
          <template v-if="importResult.detail" #default>
            <div class="result-detail">
              <p v-if="importResult.detail.total">总计：{{ importResult.detail.total }} 条</p>
              <p v-if="importResult.detail.success">成功：{{ importResult.detail.success }} 条</p>
              <p v-if="importResult.detail.failed">失败：{{ importResult.detail.failed }} 条</p>
            </div>
          </template>
        </el-alert>

        <!-- 失败详情 -->
        <div v-if="importResult.errors && importResult.errors.length > 0" class="error-list">
          <el-divider content-position="left">失败详情</el-divider>
          <el-scrollbar max-height="200px">
            <div v-for="(error, index) in importResult.errors" :key="index" class="error-item">
              <span class="error-row">第 {{ error.row }} 行：</span>
              <span class="error-msg">{{ error.message }}</span>
            </div>
          </el-scrollbar>
        </div>
      </div>

      <!-- 额外表单字段 -->
      <el-form
        v-if="$slots.form"
        ref="formRef"
        :model="formData"
        :rules="formRules"
        label-width="100px"
        class="import-form"
      >
        <slot name="form" :form-data="formData" />
      </el-form>
    </div>

    <template #footer>
      <div class="dialog-footer">
        <el-button @click="handleCancel" :disabled="uploading">
          {{ importResult ? '关闭' : '取消' }}
        </el-button>
        <el-button v-if="!importResult" type="primary" :loading="uploading" @click="handleConfirm">
          开始导入
        </el-button>
      </div>
    </template>
  </el-dialog>
</template>

<script setup lang="ts">
  import { ref, computed } from 'vue'
  import type {
    FormInstance,
    FormRules,
    UploadInstance,
    UploadUserFile,
    UploadProgressEvent
  } from 'element-plus'
  import { ElMessage } from 'element-plus'
  import { Download, UploadFilled } from '@element-plus/icons-vue'

  interface ImportResult {
    success: boolean
    message: string
    detail?: {
      total?: number
      success?: number
      failed?: number
    }
    errors?: Array<{
      row: number
      message: string
    }>
  }

  interface Props {
    modelValue: boolean
    title?: string
    width?: string | number
    // 模板下载地址
    templateUrl?: string
    // 文件上传地址（如果使用 action 方式）
    uploadAction?: string
    // 接受的文件类型
    accept?: string
    // 最大文件大小（MB）
    maxSize?: number
    // 表单验证规则
    formRules?: FormRules
  }

  interface Emits {
    (e: 'update:modelValue', value: boolean): void
    (e: 'confirm', file: File, formData?: Record<string, any>): Promise<ImportResult> | void
    (e: 'cancel'): void
  }

  const props = withDefaults(defineProps<Props>(), {
    title: '导入数据',
    width: '600px',
    uploadAction: '#',
    accept: '.xlsx,.xls',
    maxSize: 10
  })

  const emit = defineEmits<Emits>()

  const uploadRef = ref<UploadInstance>()
  const formRef = ref<FormInstance>()
  const fileList = ref<UploadUserFile[]>([])
  const formData = ref<Record<string, any>>({})
  const uploading = ref(false)
  const uploadProgress = ref(0)
  const importResult = ref<ImportResult>()

  const visible = computed({
    get: () => props.modelValue,
    set: (val) => {
      emit('update:modelValue', val)
    }
  })

  const maxSizeMB = computed(() => props.maxSize)
  const acceptText = computed(() => props.accept.replace(/\./g, '').toUpperCase())

  const handleDownloadTemplate = () => {
    if (props.templateUrl) {
      window.open(props.templateUrl, '_blank')
    }
  }

  const handleBeforeUpload = (file: File) => {
    const isValidType = props.accept.split(',').some((type) => {
      const ext = type.trim()
      return file.name.toLowerCase().endsWith(ext)
    })

    if (!isValidType) {
      console.log(`只能上传 ${acceptText.value} 格式的文件`)
      return false
    }

    const isLtSize = file.size / 1024 / 1024 < props.maxSize
    if (!isLtSize) {
      console.log(`文件大小不能超过 ${props.maxSize}MB`)
      return false
    }

    return true
  }

  const handleUploadProgress = (event: UploadProgressEvent) => {
    uploadProgress.value = Math.round(event.percent)
  }

  const handleUploadSuccess = () => {
    uploading.value = false
    ElMessage.success('导入成功')
  }

  const handleUploadError = () => {
    uploading.value = false
    console.log('导入失败')
  }

  const handleConfirm = async () => {
    if (fileList.value.length === 0) {
      ElMessage.warning('请选择要导入的文件')
      return
    }

    // 验证表单（如果有）
    if (formRef.value) {
      try {
        await formRef.value.validate()
      } catch {
        ElMessage.warning('请检查表单填写')
        return
      }
    }

    const file = fileList.value[0].raw
    if (!file) return

    uploading.value = true
    uploadProgress.value = 0

    try {
      const result = await emit('confirm', file, formData.value)
      if (result) {
        importResult.value = result
      }
    } catch (error: any) {
      importResult.value = {
        success: false,
        message: error.message || '导入失败'
      }
    } finally {
      uploading.value = false
    }
  }

  const handleCancel = () => {
    visible.value = false
    emit('cancel')
  }

  const handleClosed = () => {
    fileList.value = []
    formRef.value?.resetFields()
    formData.value = {}
    uploadProgress.value = 0
    importResult.value = undefined
  }

  defineExpose({
    formData
  })
</script>

<style scoped lang="scss">
  .import-dialog-content {
    display: flex;
    flex-direction: column;
    gap: 16px;

    .template-section {
      margin-bottom: 8px;
    }

    .upload-area {
      :deep(.el-upload) {
        width: 100%;
      }

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

      .upload-icon {
        margin-bottom: 16px;
        font-size: 48px;
        color: var(--el-color-primary);
      }

      .upload-text {
        font-size: 14px;
        color: var(--el-text-color-regular);

        em {
          font-style: normal;
          color: var(--el-color-primary);
        }

        .upload-tip {
          margin-top: 8px;
          font-size: 12px;
          color: var(--el-text-color-secondary);
        }
      }
    }

    .upload-progress {
      padding: 20px 0;
      text-align: center;

      p {
        margin-top: 12px;
        font-size: 14px;
        color: var(--el-text-color-secondary);
      }
    }

    .import-result {
      .result-detail {
        margin-top: 8px;
        font-size: 14px;
        line-height: 1.6;

        p {
          margin: 4px 0;
        }
      }

      .error-list {
        margin-top: 16px;

        .error-item {
          padding: 8px 12px;
          margin-bottom: 8px;
          font-size: 13px;
          line-height: 1.6;
          background-color: var(--el-fill-color-light);
          border-radius: 4px;

          .error-row {
            font-weight: 600;
            color: var(--el-color-danger);
          }

          .error-msg {
            color: var(--el-text-color-regular);
          }
        }
      }
    }

    .import-form {
      padding-top: 16px;
      margin-top: 16px;
      border-top: 1px solid var(--el-border-color-lighter);
    }
  }

  .dialog-footer {
    display: flex;
    gap: 12px;
    justify-content: flex-end;
  }
</style>
