<template>
	<view style="width: 100%;">
		<button @click="choseFiles" size="mini" type="primary" :disabled="disabled">选择</button>
		<view v-for="(item, index) in fileList" :key="index" style="height: 16px; margin-bottom: 12px;">
			<view style="display:flex; justify-content: space-between;">
				<view style="color:blue" @click="preview(item)">{{ item.name }}</view>
				<view style="color:red;font-weight: bold;" @click="handleRemove(index)" v-if="disabled == false">×</view>
			</view>
			<view style="height:2px"></view>
			<progress :percent="item.percent" activeColor="#4caf50" backgroundColor="#e0e0e0" stroke-width="2" />
		</view>
		<!-- 文件预览弹窗 -->
		<view v-if="showPreview" class="xt-preview-mask" @click="showPreview = false">
			<view class="xt-preview-modal" @click.stop>
				<view class="xt-preview-header">
					<text class="xt-preview-title">{{ previewItem?.name }}</text>
					<view class="xt-preview-close" @click="showPreview = false">×</view>
				</view>
				<iframe :src="previewItem?.url" class="xt-preview-iframe"></iframe>
			</view>
		</view>
	</view>
</template>

<script setup>
    // FILE_TYPE_DOC = 10
    // FILE_TYPE_VIDEO = 20
    // FILE_TYPE_AUDIO = 30
    // FILE_TYPE_PIC = 40
    // FILE_TYPE_OTHER = 50
import config from '@/utils/config.js'
import { ref, onMounted, watch, defineEmits } from 'vue';
const emit = defineEmits(["update:modelValue", "update:obj"]);

const props = defineProps({
	xtype: { type: String, default: "path" },       // path 或 id
	modelValue: { type: [Array, String], default: ()=>{[]} },
	obj: { type: Object, default: () => ({}) },
	accept: { type: String, default: '' },
	countMax: { type: Number, default: 1 },
	sizeMax: { type: Number, default: 1024 * 1024 * 5 },
	disabled: { type: Boolean, default: false },
});

// ⚠ reactive([]) 不能整体赋值，用 ref 更合理
const fileList = ref([])
const disabled = ref(props.disabled)
const showPreview = ref(false)
const previewItem = ref(null)

// header / action
const header = {
	Authorization: `Bearer ${uni.getStorageSync('access')}`
}
const action = `${config.baseUrl}/file/`

const inited = ref(false)
onMounted(() => {
	setTimeout(initFileList, 1000)
	// checkPropsUntilReady()
})

const checkPropsUntilReady = () => {
    if (inited.value) return

    if (props.modelValue !== "pending") {
        initFileList()
        inited.value = true
        return
    }
    // ⭐ 每 200ms 查一次（非常轻量）
    setTimeout(checkPropsUntilReady, 200)
}

const changeVal = () => {
	let val = null;
	if (props.xtype == "id") {
		if (props.countMax > 1){
			val= []
			fileList.value.forEach(item => {
				if(item.id){
					val.push(item.id)
				}
			})
		}else if (props.countMax == 1){
			val = null;
			if (fileList.value && fileList.value.length > 0 && fileList.value[0].id) {
				val = fileList.value[0].id
			}
		}
	}else if (props.xtype == "path"){
		if (props.countMax > 1){
			val = []
			fileList.value.forEach(item => {
				if(item.path && item.percent == 100){
					val.push(item.path)
				}
			})
		}else if (props.countMax == 1){
			val = null;
			if (fileList.value && fileList.value.length > 0 && fileList.value[0].path && fileList.value[0].percent == 100) {
				val = fileList.value[0].path
			}
		}
	}
	
	let obj = null;
	emit("update:modelValue", val)
	if (props.countMax > 1) {
		obj = fileList.value
	    emit("update:obj", obj)
	}else{
		if (fileList.value && fileList.value.length > 0) {
			obj = fileList.value[0]
			emit("update:obj", obj)
		} else {
			emit("update:obj", obj)
		}
	}
	console.log(val, obj)
}

const getFileType = (path) =>{
	let type = path.substring(path.lastIndexOf('.') + 1, path.length).toLowerCase()
	if (type === 'png' || type === 'jpg' || type === 'jpeg' || type === 'gif' || type === 'bmp') {
		return 40
	}
	else if (type === 'mp4' || type === 'avi' || type === 'rmvb') {
		return 20
	}
	else if (type === 'mp3' || type === 'wav' || type === 'wma') {
		return 30
	}
	return 10
}
/**
 * 初始化 fileList
 */
const initFileList = () => {
	if (props.countMax > 1) {
		let clist = []

		// xtype = id 情况
		if (props.xtype === "id" && Array.isArray(props.obj) && props.obj.length > 0) {

			props.obj.forEach(item => {
				clist.push({
					...item,
					url: `${config.hostUrl}${item.path}`,
					percent: 100
				})
			})
			fileList.value = clist
		}
		else if (props.xtype === "path" && props.modelValue) {
			props.modelValue.forEach(item => {
			    clist.push({
					name: item.substring(item.lastIndexOf('/') + 1, item.length),
					path: item,
					url: `${config.hostUrl}${item}`,
					percent: 100,
					type: getFileType(item)
				})
			})
			fileList.value = clist
		}
	} else if (props.countMax == 1) {
		let clist = []
		if (props.xtype === "id" && props.modelValue) {
			clist.push({
				...props.obj,
				url: `${config.hostUrl}${props.obj.path}`,
				percent: 100
			})
			fileList.value = clist
		} else if (props.xtype === "path" && props.modelValue) {
		    clist.push({
				name: item.substring(item.lastIndexOf('/') + 1, item.length),
				path: props.modelValue,
				url: `${config.hostUrl}${props.modelValue}`,
				percent: 100,
				type: getFileType(props.obj.path)
			})
			fileList.value = clist
		}
	}
}

const handleRemove = (index) => {
	let upTask = fileList.value[index].upTask
	if (upTask) {
		upTask.abort()
	}
    fileList.value.splice(index, 1)
	changeVal()
}

const preview = (item) => {
	if (item.type == 40) {
		// 获取所有类型为 40 的图片 URL
		const urls = fileList.value
			.filter(file => file.type === 40)
			.map(file => file.url)
		
		// 找到当前图片的索引
		const currentIndex = urls.indexOf(item.url)
		
		uni.previewImage({
			current: currentIndex >= 0 ? currentIndex : 0,
			urls: urls,
			fail: function(err) {
				console.log(err);
				uni.showToast({
				    title: "预览失败",
					icon: "none"
				})
			}
		})
	} else if (item.type == 10) {
		previewItem.value = item
		showPreview.value = true
	} else if (item.type == 20) {
	    uni.showToast({
		    title: "暂不支持预览该文件",
			icon : 'none'
		})
	} else if (item.type == 30) {
	    uni.showToast({
		    title: "暂不支持预览该文件",
			icon : 'none'
		})
	} else {
		uni.showToast({
		    title: "暂不支持预览该文件",
			icon : 'none'
		})
	}
}

const choseFiles = () => {
	if (fileList.value.length >= props.countMax) {
		uni.showToast({
			title: `最多只能上传${props.countMax}个文件`,
			icon: 'none'
		})
		return
	}

	uni.chooseFile({
		count: props.countMax - fileList.value.length,
		success(res) {
			const tempFiles = res.tempFiles;

			tempFiles.forEach(item => {
				// 文件大小校验（单位：字节）
				if (item.size > props.sizeMax * 1024 * 1024) {
					uni.showToast({
						title: `文件大小不能超过${props.sizeMax}M`,
						icon: 'none'
					})
					return;
				}

				// 创建上传任务
				const upTask = uni.uploadFile({
					url: action,
					filePath: item.path,
					name: 'file',
					formData: {},
					header: header,
					success: (uploadRes) => {
						const data = JSON.parse(uploadRes.data || "{}")
						if (data) {
							fileList.value.forEach((file, index) => {
								if (file.path === item.path) {
									fileList.value[index].url = `${config.hostUrl}${data.path}`
									fileList.value[index].path = data.path
									fileList.value[index].percent = 100
									fileList.value[index].id = data.id
									fileList.value[index].upTask = null
								}
							})
							// console.log("fv", fileList.value)
							changeVal()
						}
					},
					fail: (err) => {
						console.log("上传失败:", err)
					}
				})

				// 添加到列表
				fileList.value.push({
					name: item.name,
					url: null,
					path: item.path,
					percent: 0,
					type: getFileType(item.name),
					upTask: upTask
				})

				// 🔥 关键修复：关联上传进度
				upTask.onProgressUpdate((res) => {
					fileList.value.forEach((file, index) => {
						if (file.path === item.path) {
							fileList.value[index].percent = res.progress
						}
					})
				});
			})
		}
	})
}
</script>

<style scoped>
.xt-preview-mask {
	position: fixed;
	top: 0;
	left: 0;
	right: 0;
	bottom: 0;
	background: rgba(0, 0, 0, 0.5);
	z-index: 9999;
	display: flex;
	align-items: center;
	justify-content: center;
}
.xt-preview-modal {
	width: 90vw;
	height: 85vh;
	background: #fff;
	border-radius: 16rpx;
	display: flex;
	flex-direction: column;
	overflow: hidden;
}
.xt-preview-header {
	display: flex;
	justify-content: space-between;
	align-items: center;
	padding: 20rpx 24rpx;
	border-bottom: 1px solid #e5e7eb;
	flex-shrink: 0;
}
.xt-preview-title {
	font-size: 28rpx;
	font-weight: 500;
	color: #1f2937;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	flex: 1;
}
.xt-preview-close {
	font-size: 40rpx;
	color: #6b7280;
	cursor: pointer;
	padding: 0 16rpx;
	font-weight: bold;
}
.xt-preview-iframe {
	flex: 1;
	width: 100%;
	border: none;
}
</style>
