<template>
    <a-upload 
        :multiple="multiple" 
        @change="handleChange" 
        v-model:file-list="fileList" 
        :custom-request="handleCustomRequest"
        :show-upload-list="{ showRemoveIcon: allowClear }"
    >
        <a-button>
            <upload-outlined></upload-outlined>
            {{ loading ? loadingBtnText : btnText }}
        </a-button>
    </a-upload>
</template>

<script setup>
import { Form, message } from 'ant-design-vue'
import { onMounted, ref, watch } from 'vue'
import apis from '@/apis'
import { config } from '@/config'

defineOptions({
    name: 'XUploadInput',
})

const fileList = ref([])
const loading = ref(false)

/**
 * 组件属性
 */
const props = defineProps({
    modelValue: { 
        type: Array, 
        default: () => [] 
    },
    btnText: {
        type: String,
        default: '选择文件',
    },
    loadingBtnText: {
        type: String,
        default: '上传中',
    },
    allowClear: {
        type: Boolean,
        default: true,
    },
    multiple: {
        type: Boolean,
        default: false,
    }
})

const emit = defineEmits(['update:modelValue', 'change', 'uploadSuccess', 'uploadError'])

const { onFieldChange } = Form.useInjectFormItemContext()

/**
 * 初始化文件列表
 */
const initFileList = () => {
    if (props.modelValue && props.modelValue.length > 0) {
        fileList.value = props.modelValue.map(url => ({
            uid: `preview-${Date.now()}-${Math.random()}`,
            name: url.substring(url.lastIndexOf('/') + 1),
            status: 'done',
            url: url
        }))
    } else {
        fileList.value = []
    }
}

onMounted(() => {
    initFileList()
})

/**
 * 监听外部值变化
 */
watch(() => props.modelValue, (newVal) => {
    // 只有当 fileList 中的完成文件URL与外部值不一致时才更新
    const doneUrls = fileList.value
        .filter(f => f.status === 'done' && f.url)
        .map(f => f.url)
    
    if (JSON.stringify(newVal) !== JSON.stringify(doneUrls)) {
        initFileList()
    }
}, { deep: true })

/**
 * 自定义上传请求
 */
const handleCustomRequest = async (options) => {
    const { file, onProgress, onSuccess, onError } = options

    loading.value = true

    try {
        const formData = new FormData()
        formData.append('file', file)

        // 模拟上传进度
        const progressInterval = setInterval(() => {
            if (onProgress) {
                const percent = Math.min(95, (file.percent || 0) + 10)
                file.percent = percent
                onProgress({ percent })
            }
        }, 200)

        const { data } = await apis.common.uploadFile(formData)
        clearInterval(progressInterval)

        const fullUrl = config('http.apiUpload') + data.saved_path
        
        // 完成进度
        if (onProgress) {
            onProgress({ percent: 100 })
        }

        onSuccess({
            url: fullUrl
        }, file)

        emit('uploadSuccess', { url: fullUrl })

    } catch (err) {
        console.error('上传失败:', err)
        onError(err)
        emit('uploadError', err)
        message.error('上传失败')
    } finally {
        loading.value = false
    }
}

/**
 * 处理文件变化
 */
const handleChange = ({ file, fileList: updatedList }) => {
    console.log('文件状态变化:', file.status)

    switch (file.status) {
        case 'uploading':
            loading.value = true
            break
            
        case 'done':
            loading.value = false
            // 确保文件对象有正确的URL
            const responseUrl = file.response?.url
            if (responseUrl) {
                const targetFile = updatedList.find(f => f.uid === file.uid)
                if (targetFile) {
                    targetFile.url = responseUrl
                }
                message.success(`${file.name} 上传成功`)
            }
            updateModelValue(updatedList)
            break
            
        case 'error':
            loading.value = false
            message.error(`${file.name} 上传失败`)
            break
            
        case 'removed':
            updateModelValue(updatedList)
            break
    }
}

/**
 * 更新模型值
 */
const updateModelValue = (fileList) => {
    const urls = fileList
        .filter(item => item.status === 'done' && item.url)
        .map(item => item.url)
    
    emit('update:modelValue', urls)
    emit('change', urls)
    onFieldChange()
}
</script>

<style lang="less" scoped>
:deep(.ant-upload-wrapper) {
    .ant-btn {
        display: inline-flex;
        align-items: center;
        gap: 4px;
    }
    
    .ant-upload-list {
        margin-top: 8px;
    }
}
</style>