<template>
	<view class="nbd-photo-upload">
		<view class="nbd-photo-upload__grid">
			<view class="nbd-photo-upload__item" v-for="(photo, index) in localPhotos" :key="photo._id">
				<image class="nbd-photo-upload__img" :src="photo.src" mode="aspectFill" @click="handlePreview(index)"></image>
				<view class="nbd-photo-upload__tag" v-if="photo.uploaded">&#10003;</view>
				<view class="nbd-photo-upload__progress" v-if="photo.uploading">
					<view class="nbd-photo-upload__progress-bar" :style="{ width: photo.progress + '%' }"></view>
				</view>
				<view class="nbd-photo-upload__delete" @tap.stop="handleDelete(index)">
					<u-icon name="close" color="#fff" size="14"></u-icon>
				</view>
			</view>
			<view class="nbd-photo-upload__item nbd-photo-upload__add" @click="handleTakePhoto" v-if="localPhotos.length < maxCount">
				<u-icon name="camera" color="#ccc" size="40"></u-icon>
				<text class="nbd-photo-upload__add-text">拍照</text>
			</view>
		</view>
	</view>
</template>

<script setup>
import { ref, watch } from 'vue'
import { uploadAttach } from '@/api/base.js'
import { baseFileUrl, parseAttachUrls } from '@/utils/request.js'

const props = defineProps({
	attachUrl: { type: String, default: '' },
	maxCount: { type: Number, default: 6 },
	typeName: { type: String, default: '' }
})

const emit = defineEmits(['update:attachUrl'])

const localPhotos = ref([])
let photoIdSeed = 0

// 回显已有照片
watch(() => props.attachUrl, (val) => {
	if (val && localPhotos.value.length === 0) {
		localPhotos.value = parseAttachUrls(val, 0)
		photoIdSeed = localPhotos.value.length
	}
}, { immediate: true })

const isLocalPath = (src) => {
	if (!src) return false
	// 已有服务端附件不需要重复上传
	if (src.startsWith(baseFileUrl)) return false
	return true
}

// 同步 emit
const syncAttachUrl = () => {
	const urls = localPhotos.value
		.filter(p => p.uploaded && p._attachUrl)
		.map(p => p._attachUrl)
	emit('update:attachUrl', urls.join(','))
}

const handleTakePhoto = () => {
	uni.chooseImage({
		count: 1,
		sourceType: ['camera'],
		success: (res) => {
			const tempPath = res.tempFilePaths[0]
			const id = ++photoIdSeed
			localPhotos.value.push({
				_id: id,
				src: tempPath,
				uploaded: false
			})
		}
	})
}

const handlePreview = (index) => {
	const urls = localPhotos.value.map(p => p.src)
	uni.previewImage({ current: index, urls })
}

const handleDelete = (index) => {
	uni.showModal({
		title: '确认删除',
		content: '确定要删除这张照片吗？',
		success: ({ confirm }) => {
			if (confirm) {
				localPhotos.value.splice(index, 1)
				syncAttachUrl()
			}
		}
	})
}

// 暴露：外部调用批量上传
const uploadAll = async () => {
	const pending = localPhotos.value.filter(p => !p.uploaded && isLocalPath(p.src))
	for (const photo of pending) {
		photo.uploading = true
		photo.progress = 0
		try {
			const result = await uploadAttach(photo.src, { typeName: props.typeName }, (progress) => {
				photo.progress = progress
			})
			photo.uploading = false
			photo.uploaded = true
			const url = Array.isArray(result) ? result[0] : result
			if (url) {
				photo._attachUrl = url
				photo.src = `${baseFileUrl}${url}`
			}
		} catch (e) {
			photo.uploading = false
			console.error('照片上传失败:', e)
			uni.showToast({ title: '照片上传失败，请重试', icon: 'none' })
			throw e
		}
	}
	syncAttachUrl()
}

// 暴露：是否有待上传的照片
const hasPending = () => localPhotos.value.some(p => !p.uploaded && isLocalPath(p.src))

defineExpose({ uploadAll, hasPending })
</script>

<style scoped lang="scss">
.nbd-photo-upload {
	width: 100%;

	&__grid {
		display: flex;
		flex-wrap: wrap;
		margin: -8rpx;
	}

	&__item {
		width: 200rpx;
		height: 200rpx;
		margin: 8rpx;
		border-radius: 12rpx;
		overflow: hidden;
		position: relative;
		background: #f5f6f8;
		flex-shrink: 0;
	}

	&__img {
		width: 100%;
		height: 100%;
	}

	&__tag {
		position: absolute;
		top: 6rpx;
		left: 6rpx;
		width: 36rpx;
		height: 36rpx;
		border-radius: 50%;
		background: rgba(0, 200, 83, 0.85);
		color: #fff;
		font-size: 22rpx;
		display: flex;
		align-items: center;
		justify-content: center;
	}

	&__progress {
		position: absolute;
		bottom: 0;
		left: 0;
		right: 0;
		height: 6rpx;
		background: rgba(0, 0, 0, 0.3);

		&-bar {
			height: 100%;
			background: #3577ff;
			transition: width 0.3s ease;
		}
	}

	&__delete {
		position: absolute;
		top: 6rpx;
		right: 6rpx;
		width: 36rpx;
		height: 36rpx;
		border-radius: 50%;
		background: rgba(0, 0, 0, 0.5);
		display: flex;
		align-items: center;
		justify-content: center;
	}

	&__add {
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: center;
		border: 2rpx dashed #ddd;

		&-text {
			font-size: 24rpx;
			color: #ccc;
			margin-top: 8rpx;
		}
	}
}
</style>
