<template>
	<div class="file-upload">
		<a-upload v-model:file-list="fileList" :custom-request="customUpload" :before-upload="beforeUpload" :accept="accept" :max-count="maxCount" :disabled="disabled" :multiple="multiple" @change="handleChange" @remove="handleRemove">
			<a-button v-if="!disabled">
				<upload-outlined />
				上传文件
			</a-button>
		</a-upload>
	</div>
</template>

<script setup>
import { ref, watch } from 'vue'
import { message } from 'ant-design-vue'
import { UploadOutlined } from '@ant-design/icons-vue'
import uploadConfig from '@/config/upload'

const props = defineProps({
	// 文件列表
	modelValue: {
		type: [Array, String],
		default: () => [],
	},
	// 最大上传数量，默认1为单文件上传
	maxCount: {
		type: Number,
		default: 1,
	},
	// 接受的文件类型，例如 '.pdf,.doc,.docx' 或 '*'
	accept: {
		type: String,
		default: '*',
	},
	// 是否禁用
	disabled: {
		type: Boolean,
		default: false,
	},
	// 是否支持多选
	multiple: {
		type: Boolean,
		default: false,
	},
	// 是否返回URL字符串（单文件）或URL数组（多文件）
	returnUrl: {
		type: Boolean,
		default: true,
	},
})

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

// 文件列表
const fileList = ref([])

// 初始化文件列表
const initFileList = () => {
	if (props.modelValue) {
		if (typeof props.modelValue === 'string') {
			// 单文件上传，字符串格式
			fileList.value = props.modelValue
				? [
						{
							uid: '-1',
							name: 'file',
							status: 'done',
							url: props.modelValue,
							response: {
								src: props.modelValue,
							},
						},
					]
				: []
		} else if (Array.isArray(props.modelValue)) {
			// 多文件上传，数组格式
			fileList.value = props.modelValue.map((url, index) => ({
				uid: `-${index}`,
				name: `file${index}`,
				status: 'done',
				url: url,
				response: {
					src: url,
				},
			}))
		}
	} else {
		fileList.value = []
	}
}

// 监听外部值变化
watch(
	() => props.modelValue,
	() => {
		initFileList()
	},
	{ immediate: true },
)

// 自定义上传
const customUpload = (options) => {
	const { file, onProgress, onSuccess, onError } = options
	const formData = new FormData()
	formData.append(uploadConfig.filename || 'file', file)

	// 使用文件上传API对象
	const apiObj = uploadConfig.apiObjFile || uploadConfig.apiObj

	apiObj(formData, {
		onUploadProgress: (progressEvent) => {
			const percent = Math.round((progressEvent.loaded / progressEvent.total) * 100)
			onProgress({ percent }, file)
		},
	})
		.then((res) => {
			const data = uploadConfig.parseData(res)
			if (data.code === uploadConfig.successCode) {
				onSuccess(data, file)
				message.success('上传成功')
			} else {
				onError(new Error(data.msg || '上传失败'))
				message.error(data.msg || '上传失败')
			}
		})
		.catch((error) => {
			onError(error)
			message.error('上传失败：' + error.message)
		})
}

// 上传前校验
const beforeUpload = (file) => {
	const maxSizeMB = uploadConfig.maxSizeFile || uploadConfig.maxSize || 10
	const maxSizeBytes = maxSizeMB * 1024 * 1024

	if (file.size > maxSizeBytes) {
		message.error(`文件大小不能超过 ${maxSizeMB}MB`)
		return false
	}
	return true
}

// 处理文件列表变化
const handleChange = ({ fileList: newFileList }) => {
	fileList.value = newFileList

	// 提取成功的文件URL
	const successFiles = newFileList.filter((file) => file.status === 'done' && (file.url || file.response?.src)).map((file) => file.url || file.response?.src)

	// 触发更新事件
	if (props.returnUrl) {
		// 返回URL字符串或数组
		const value = props.maxCount === 1 ? successFiles[0] || '' : successFiles
		emit('update:modelValue', value)
		emit('change', value, newFileList)
	} else {
		// 返回完整文件列表
		emit('update:modelValue', newFileList)
		emit('change', newFileList)
	}
}

// 处理文件移除
const handleRemove = (file) => {
	emit('remove', file)
	return true
}
</script>

<style scoped>
.file-upload {
	width: 100%;
}
</style>
