<template>
    <el-dialog
        v-model="dialogVisible"
        :title="parameter.title"
        :destroy-on-close="true"
        width="450px"
        :close-on-click-modal="!parameter.progressBar"
        draggable
    >
        <el-upload
            ref="uploadRef"
            action="#"
            class="upload"
            :limit="1"
            :http-request="uploadZip"
            accept=".zip"
            :auto-upload="!parameter.confirmMessage"
            :on-change="handleChange"
            :on-remove="handleRemove"
            :disabled="fileDisabled"
        >
            <slot name="empty">
                <el-button type="primary" icon="Upload">点击上传</el-button>
            </slot>
            <template #tip>
                <slot name="tip">
                    <div class="el-upload__tip">请上传 .zip 标准格式文件</div>
                </slot>
            </template>
        </el-upload>
        <el-progress
            v-if="parameter.progressBar"
            :status="progressData.status"
            :percentage="progressData.percentage"
        ></el-progress>
        <el-text v-if="parameter.progressBar && progressData.status === 'exception'" size="small" type="danger">
            {{ progressData.message }}
        </el-text>
        <el-text v-if="parameter.progressBar && progressData.status === 'success'" size="small" type="success">
            {{ progressData.message }}
        </el-text>
        <el-text v-if="parameter.progressBar && progressData.status === ''" size="small" type="info">
            {{ progressData.message }}
        </el-text>

        <template #footer v-if="parameter.confirmMessage">
            <el-button :disabled="disable" type="primary" @click="uploadSubmit">开始导入</el-button>
        </template>
    </el-dialog>
</template>

<script setup lang="ts" name="ImportZip">
import { ref } from 'vue'
import type { UploadInstance, UploadProps, UploadRequestOptions } from 'element-plus'
import http from '@/api'

export interface ZipParameterProps {
    title: string // 标题
    patternId?: string // 模式ID
    planId?: string // 计划ID
    importApi?: (params: any) => Promise<any> // 批量导入的Api
    confirmMessage?: string // 提示信息
    progressBar?: boolean // 进度条
}
// dialog状态
const dialogVisible = ref(false)
const disable = ref(true)
const fileDisabled = ref(false)
const uploadRef = ref<UploadInstance>()

// 父组件传过来的参数
const parameter = ref<ZipParameterProps>({
    title: ''
})
const emit = defineEmits<{
    (e: 'result', data: boolean): void
}>()
// 接收父组件参数
const acceptParams = (params: ZipParameterProps) => {
    parameter.value = { ...parameter.value, ...params }
    dialogVisible.value = true
}

// 文件上传
const uploadZip = (param: UploadRequestOptions) => {
    let zipFormData = new FormData()
    zipFormData.append('file', param.file)
    if (parameter.value.patternId) {
        zipFormData.append('patternId', parameter.value.patternId)
    }
    if (parameter.value.planId) {
        zipFormData.append('planId', parameter.value.planId)
    }
    if (parameter.value.progressBar) {
        initSSE()
    }

    setTimeout(() => {
        parameter.value.importApi!(zipFormData).then(res => handleImportResponse(res))
    }, 1000)
}

const handleImportResponse = (res: any) => {
    if (!parameter.value.progressBar) {
        if (res.code === 'A0000') {
            ElMessage.success('导入成功')
        } else {
            ElMessage.error(res.message)
        }
        dialogVisible.value = false
        emit('result', res.data)
    } else {
        //
    }
}

const uploadSubmit = () => {
    if (!uploadRef.value) {
        return ElMessage.warning('请选择文件！')
    }
    progressData.value = {
        percentage: 0,
        status: '',
        message: ''
    }
    ElMessageBox.confirm(parameter.value.confirmMessage, '温馨提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
    })
        .then(() => {
            disable.value = true
            fileDisabled.value = true
            uploadRef.value?.submit()
        })
        .catch(() => {
            disable.value = false
            fileDisabled.value = false
        })
}
const handleChange: UploadProps['onChange'] = (uploadFile, uploadFiles) => {
    disable.value = uploadFiles.length === 0
    progressData.value = {
        percentage: 0,
        status: '',
        message: ''
    }
}
const handleRemove: UploadProps['onRemove'] = (uploadFile, uploadFiles) => {
    disable.value = uploadFiles.length === 0
    progressData.value = {
        percentage: 0,
        status: '',
        message: ''
    }
}

const progressData = ref({
    percentage: 0,
    status: '',
    message: ''
})
const eventSource = ref<EventSource | null>(null)

const initSSE = () => {
    eventSource.value = http.sse('/sse/createSse')

    eventSource.value.onmessage = event => {
        console.log('收到消息内容是:', event.data)
        const res = JSON.parse(event.data)
        progressData.value.percentage = res.data
        progressData.value.message = res.message
        if (res.code === 'A0002') {
            fileDisabled.value = false
            disable.value = false
            progressData.value.status = 'exception'
            ElMessage.error(res.message)
        }
        if (progressData.value.percentage === 100) {
            progressData.value.status = 'success'
            eventSource.value!.close()
            ElMessage.success('导入成功')
            dialogVisible.value = false
            emit('result', true)
        }
    }

    eventSource.value.onerror = error => {
        console.warn('SSE 连接出错：', error)
        eventSource.value!.close()
    }
}
// 添加一个手动关闭EventSource的函数
const closeEventSource = () => {
    if (eventSource.value) {
        eventSource.value.close()
        eventSource.value = null
        console.log('SSE连接已关闭')
    }
}
// 监听 dialogVisible 的变化，确保在对话框关闭时清理资源
watch(dialogVisible, newVal => {
    if (!newVal) {
        // 延迟执行，确保在组件完全关闭后清理
        setTimeout(() => {
            closeEventSource()
            fileDisabled.value = false
            disable.value = false
            progressData.value = {
                percentage: 0,
                status: '',
                message: ''
            }
        }, 100)
    }
})
onUnmounted(() => {
    closeEventSource()
})
defineExpose({
    acceptParams
})
</script>
<style lang="scss" scoped>
@use './index.scss';
</style>
