<template>
	<view class="media-uploader">
		<view class="media-grid">
			<view class="media-item" v-for="(item, index) in mediaList" :key="index">
				<!-- 图片预览 -->
				<image v-if="item.type === 'image'" :src="item.url" mode="aspectFill" @tap="previewMedia(index)">
				</image>
				<!-- 视频预览 -->
				<video v-else-if="item.type === 'video'" :id="'video-' + index" :src="item.url" class="video-preview"
					controls show-center-play-btn enable-play-gesture show-fullscreen-btn object-fit="cover"
					:initial-time="0" :show-mute-btn="true" :enable-progress-gesture="true" :vslide-gesture="true"
					:vslide-gesture-in-fullscreen="true" @tap="previewVideo(index)" :poster="item.thumbnail"></video>
				<!-- 删除按钮 -->
				<view class="delete-btn" @tap.stop="deleteMedia(index)">
					<uni-icons type="close" size="12" color="#fff"></uni-icons>
				</view>

			</view>

			<!-- 上传按钮 -->
			<view class="upload-trigger" v-if="mediaList.length < maxCount">
				<view class="upload-box" @tap="chooseMedia">
					<uni-icons type="camera" size="24" color="#999"></uni-icons>
					<text class="upload-text">{{mediaList.length}}/{{maxCount}}</text>
				</view>
			</view>
		</view>
		<text class="upload-tip">最多上传{{maxCount}}个文件</text>
	</view>
</template>

<script>
	export default {
		name: 'MediaUploader',
		props: {
			// 最大上传数量
			maxCount: {
				type: Number,
				default: 9
			},
			// 已有的媒体列表
			value: {
				type: Array,
				default: () => []
			},
			// 上传地址
			uploadUrl: {
				type: String,
				required: true
			},
			// 认证token
			token: {
				type: String,
				required: true
			},
			// 媒体类型限制
			mediaType: {
				type: String,
				default: 'all', // 可选值：'all'、'image'、'video'
				validator: function(value) {
					return ['all', 'image', 'video'].includes(value)
				}
			},
			// 是否使用媒体模式（拍照/相册）
			media: {
				type: Boolean,
				default: false
			}
		},
		data() {
			return {
				mediaList: []
			}
		},
		watch: {
			value: {
				handler(newVal) {
					if (!Array.isArray(newVal)) {
						console.warn('MediaUploader: value must be an array');
						return;
					}

					this.mediaList = newVal.map(item => {
						// 如果已经是正确的格式，直接返回
						if (typeof item === 'object' && item.url && item.type) {
							return item;
						}

						// 如果是字符串，转换为对象格式
						const url = typeof item === 'object' ? item.url : item;
						return {
							url: url,
							type: this.getMediaType(item)
						}
					})
				},
				immediate: true
			}
		},
		methods: {
			// 选择媒体文件
			async chooseMedia() {
				try {
					// 检查是否达到最大数量
					if (this.mediaList.length >= this.maxCount) {
						uni.showToast({
							title: `最多只能上传${this.maxCount}个文件`,
							icon: 'none'
						});
						return;
					}

					// 获取平台信息
					const platform = uni.getSystemInfoSync().platform;
					const isH5 = platform === 'h5';

					// 如果是媒体模式
					if (this.media) {
						try {
							const res = await uni.showActionSheet({
								itemList: ['拍摄', '从相册选择']
							});

							if (res.tapIndex === 0) {
								// 拍摄模式
								if (this.mediaType === 'video') {
									this.captureVideo();
								} else {
									this.captureImage();
								}
							} else {
								// 从相册选择，支持图片和视频
								this.chooseFromAlbum();
							}
							return;
						} catch (error) {
							console.error('选择操作失败:', error);
							return;
						}
					}

					// 非媒体模式的原有逻辑
					if (this.mediaType === 'image') {
						this.chooseImage();
					} else if (this.mediaType === 'video') {
						if (isH5) {
							this.chooseVideoH5();
						} else {
							this.chooseVideoMini();
						}
					} else {
						// 如果是 'all'，则显示选择菜单
						try {
							const res = await uni.showActionSheet({
								itemList: ['选择图片', '选择视频']
							});

							if (res.tapIndex === 0) {
								this.chooseImage();
							} else {
								if (isH5) {
									this.chooseVideoH5();
								} else {
									this.chooseVideoMini();
								}
							}
						} catch (error) {
							console.error('选择操作失败:', error);
							return;
						}
					}
				} catch (e) {
					console.error(e);
				}
			},

			// 选择图片
			async chooseImage() {
				try {
					const res = await uni.chooseImage({
						count: this.maxCount - this.mediaList.length,
						sizeType: ['original', 'compressed'],
						sourceType: ['album', 'camera']
					});

					// 上传图片
					for (let tempFilePath of res.tempFilePaths) {
						try {
							const uploadResult = await this.uploadFile(tempFilePath);
							const newMedia = {
								url: uploadResult.data.link,
								type: 'image'
							};
							this.updateMediaList([...this.mediaList, newMedia]);
						} catch (uploadError) {
							console.error('图片上传失败:', uploadError);
							uni.showToast({
								title: '图片上传失败',
								icon: 'none'
							});
						}
					}
				} catch (e) {
					console.error(e);
				}
			},

			// H5平台选择视频
			async chooseVideoH5() {
				try {
					const res = await uni.chooseVideo({
						sourceType: ['album', 'camera'],
						compressed: true,
						camera: 'back'
					});

					uni.showLoading({
						title: '处理中...'
					});

					try {
						// 上传视频文件
						const videoResult = await this.uploadFile(res.tempFilePath);

						const newMedia = {
							url: videoResult.data.link,
							type: 'video',
							duration: Math.round(res.duration),
							// H5暂时不支持视频预览图，可以后续在服务端处理
							thumbnail: ''
						};

						this.updateMediaList([...this.mediaList, newMedia]);
						uni.hideLoading();
					} catch (error) {
						uni.hideLoading();
						uni.showToast({
							title: '视频处理失败',
							icon: 'none'
						});
						console.error('视频处理失败:', error);
					}
				} catch (e) {
					console.error('选择视频失败:', e);
					uni.showToast({
						title: '选择视频失败',
						icon: 'none'
					});
				}
			},

			// 非H5平台选择视频（小程序和APP）
			async chooseVideoMini() {
				try {
					// #ifdef MP-WEIXIN
					// 微信小程序使用 chooseMedia
					wx.chooseMedia({
						count: 1,
						mediaType: ['video'],
						success: async (res) => {
							const tempFile = res.tempFiles[0];
							try {
								uni.showLoading({
									title: '处理中...'
								});

								// 上传视频文件
								const videoResult = await this.uploadFile(tempFile.tempFilePath);

								// 上传视频预览图
								const thumbResult = await this.uploadFile(tempFile.thumbTempFilePath);

								const newMedia = {
									url: videoResult.data.link,
									type: 'video',
									duration: Math.round(tempFile.duration),
									thumbnail: thumbResult.data.link
								};

								this.updateMediaList([...this.mediaList, newMedia]);
								uni.hideLoading();
							} catch (error) {
								uni.hideLoading();
								uni.showToast({
									title: '视频处理失败',
									icon: 'none'
								});
								console.error('视频处理失败:', error);
							}
						},
						fail: (err) => {
							console.error('选择视频失败:', err);
							uni.showToast({
								title: '选择视频失败',
								icon: 'none'
							});
						}
					});
					// #endif

					// #ifdef APP-PLUS
					// APP端使用 chooseVideo
					uni.chooseVideo({
						sourceType: ['camera', 'album'],
						compressed: true,
						success: async (res) => {
							try {
								uni.showLoading({
									title: '处理中...'
								});

								// 上传视频文件
								const videoResult = await this.uploadFile(res.tempFilePath);

								// 获取视频缩略图
								const thumbPath = await this.getVideoThumb(res.tempFilePath);
								let thumbnail = '';

								if (thumbPath) {
									try {
										const thumbResult = await this.uploadFile(thumbPath);
										thumbnail = thumbResult.data.link;
									} catch (error) {
										console.error('缩略图上传失败:', error);
									}
								}

								const newMedia = {
									url: videoResult.data.link,
									type: 'video',
									duration: Math.round(res.duration || 0),
									thumbnail: thumbnail || videoResult.data
										.link // 如果没有缩略图，使用视频地址作为预览图
								};

								this.updateMediaList([...this.mediaList, newMedia]);
								uni.hideLoading();
							} catch (error) {
								uni.hideLoading();
								uni.showToast({
									title: '视频处理失败',
									icon: 'none'
								});
								console.error('视频处理失败:', error);
							}
						},
						fail: (err) => {
							console.error('选择视频失败:', err);
							uni.showToast({
								title: '选择视频失败',
								icon: 'none'
							});
						}
					});
					// #endif

					// #ifdef H5
					// 如果在H5环境下不小心调用了这个方法，就调用H5的方法
					this.chooseVideoH5();
					// #endif
				} catch (e) {
					console.error('选择视频失败:', e);
					uni.showToast({
						title: '选择视频失败',
						icon: 'none'
					});
				}
			},

			// 拍摄视频
			async captureVideo() {
				try {
					const res = await uni.chooseVideo({
						sourceType: ['camera'],
						compressed: true,
						camera: 'back'
					});

					uni.showLoading({
						title: '处理中...'
					});

					try {
						// 上传视频文件
						const videoResult = await this.uploadFile(res.tempFilePath);

						const newMedia = {
							url: videoResult.data.link,
							type: 'video',
							duration: Math.round(res.duration),
							thumbnail: ''
						};

						this.updateMediaList([...this.mediaList, newMedia]);
						uni.hideLoading();
					} catch (error) {
						uni.hideLoading();
						uni.showToast({
							title: '视频处理失败',
							icon: 'none'
						});
						console.error('视频处理失败:', error);
					}
				} catch (e) {
					console.error('拍摄视频失败:', e);
					uni.showToast({
						title: '拍摄视频失败',
						icon: 'none'
					});
				}
			},

			// 拍摄图片
			async captureImage() {
				try {
					const res = await uni.chooseImage({
						count: 1,
						sizeType: ['original', 'compressed'],
						sourceType: ['camera']
					});

					// 上传图片
					for (let tempFilePath of res.tempFilePaths) {
						try {
							const uploadResult = await this.uploadFile(tempFilePath);
							const newMedia = {
								url: uploadResult.data.link,
								type: 'image'
							};
							this.updateMediaList([...this.mediaList, newMedia]);
						} catch (uploadError) {
							console.error('图片上传失败:', uploadError);
							uni.showToast({
								title: '图片上传失败',
								icon: 'none'
							});
						}
					}
				} catch (e) {
					console.error(e);
				}
			},

			// 从相册选择（支持图片和视频）
			async chooseFromAlbum() {
				// #ifdef MP-WEIXIN
				try {
					const res = await new Promise((resolve, reject) => {
						wx.chooseMedia({
							count: this.maxCount - this.mediaList.length,
							mediaType: ['image', 'video'],
							sourceType: ['album'],
							success: resolve,
							fail: reject
						});
					});

					for (let tempFile of res.tempFiles) {
						try {
							uni.showLoading({
								title: '处理中...'
							});

							// 上传文件
							const fileResult = await this.uploadFile(tempFile.tempFilePath);

							if (tempFile.fileType === 'video') {
								// 处理视频
								const thumbPath = tempFile.thumbTempFilePath;
								let thumbnail = '';
								if (thumbPath) {
									try {
										const thumbResult = await this.uploadFile(thumbPath);
										thumbnail = thumbResult.data.link;
									} catch (error) {
										console.error('缩略图上传失败:', error);
									}
								}

								const newMedia = {
									url: fileResult.data.link,
									type: 'video',
									duration: Math.round(tempFile.duration || 0),
									thumbnail: thumbnail || fileResult.data.link
								};
								this.updateMediaList([...this.mediaList, newMedia]);
							} else {
								// 处理图片
								const newMedia = {
									url: fileResult.data.link,
									type: 'image'
								};
								this.updateMediaList([...this.mediaList, newMedia]);
							}

							uni.hideLoading();
						} catch (error) {
							uni.hideLoading();
							uni.showToast({
								title: '上传失败',
								icon: 'none'
							});
							console.error('上传失败:', error);
						}
					}
				} catch (e) {
					console.error('选择失败:', e);
					uni.showToast({
						title: '选择失败',
						icon: 'none'
					});
				}
				// #endif

				// #ifdef APP-PLUS || H5
				// APP和H5使用系统相册
				try {
					const res = await uni.chooseImage({
						count: this.maxCount - this.mediaList.length,
						sizeType: ['original', 'compressed'],
						sourceType: ['album']
					});

					// 上传图片
					for (let tempFilePath of res.tempFilePaths) {
						try {
							const uploadResult = await this.uploadFile(tempFilePath);
							const newMedia = {
								url: uploadResult.data.link,
								type: 'image'
							};
							this.updateMediaList([...this.mediaList, newMedia]);
						} catch (uploadError) {
							console.error('上传失败:', uploadError);
							uni.showToast({
								title: '上传失败',
								icon: 'none'
							});
						}
					}
				} catch (e) {
					console.error(e);
				}
				// #endif
			},

			async getVideoThumb(videoPath) {
				return new Promise((resolve, reject) => {
					try {
						// #ifdef APP-PLUS
						// 先尝试使用 plus.io.getVideoInfo
						plus.io.getVideoInfo({
							filePath: videoPath,
							success: (info) => {
								if (info.thumbnail) {
									resolve(info.thumbnail);
								} else {
									// 如果获取不到缩略图，尝试使用 uni.getVideoInfo
									this.getVideoThumbUnified(videoPath).then(resolve).catch(() =>
										resolve(''));
								}
							},
							error: () => {
								// 如果 plus.io.getVideoInfo 失败，尝试使用 uni.getVideoInfo
								this.getVideoThumbUnified(videoPath).then(resolve).catch(() =>
									resolve(''));
							}
						});
						// #endif

						// #ifndef APP-PLUS
						// 非APP平台使用 uni.getVideoInfo
						this.getVideoThumbUnified(videoPath).then(resolve).catch(() => resolve(''));
						// #endif
					} catch (e) {
						console.error('获取视频缩略图失败:', e);
						resolve('');
					}
				});
			},

			// 使用 uni.getVideoInfo 获取视频缩略图
			async getVideoThumbUnified(videoPath) {
				return new Promise((resolve, reject) => {
					uni.getVideoInfo({
						src: videoPath,
						success: (res) => {
							if (res.thumbTempFilePath) {
								resolve(res.thumbTempFilePath);
							} else {
								reject(new Error('No thumbnail'));
							}
						},
						fail: reject
					});
				});
			},

			// 文件上传方法
			async uploadFile(filePath) {
				uni.showLoading({
					title: '上传中...',
					mask: true
				})
				return new Promise((resolve, reject) => {
					uni.uploadFile({
						url: this.uploadUrl,
						filePath: filePath,
						header: {
							"Blade-Auth": this.token
						},
						name: 'file',
						success: (res) => {
							resolve(JSON.parse(res.data));
							uni.hideLoading()
						},
						fail: reject
					});
				});
			},

			// 删除媒体
			deleteMedia(index) {
				const newList = [...this.mediaList];
				newList.splice(index, 1);
				this.updateMediaList(newList);
			},

			// 预览媒体
			previewMedia(index) {
				const item = this.mediaList[index];
				if (item.type === 'image') {
					const imageUrls = this.mediaList
						.filter(item => item.type === 'image')
						.map(item => item.url);
					const currentIndex = imageUrls.indexOf(item.url);

					uni.previewImage({
						urls: imageUrls,
						current: currentIndex
					});
				}
			},

			// 预览视频
			previewVideo(index) {
				const item = this.mediaList[index];
				if (item.type === 'video') {
					// H5环境下不需要特殊处理，让视频组件自己处理全屏
					// #ifdef MP-WEIXIN
					const videoContext = uni.createVideoContext(`video-${index}`, this);
					if (videoContext) {
						videoContext.requestFullScreen();
					}
					// #endif
				}
			},

			// 更新媒体列表
			updateMediaList(list) {
				this.mediaList = list;
				this.$emit('input', list.map(item => item.url));
				this.$emit('change', list);
			},

			// 获取媒体类型
			getMediaType(url) {
				// 如果已经是对象格式，直接返回其类型
				if (typeof url === 'object' && url.type) {
					return url.type;
				}

				// 如果是字符串，则通过扩展名判断
				if (typeof url === 'string') {
					const videoExts = ['.mp4', '.mov', '.avi', '.wmv'];
					const ext = url.substring(url.lastIndexOf('.')).toLowerCase();
					return videoExts.includes(ext) ? 'video' : 'image';
				}

				// 默认返回图片类型
				return 'image';
			}
		}
	}
</script>

<style lang="scss" scoped>
	.media-uploader {
		padding: 15px;

		.media-grid {
			display: flex;
			flex-wrap: wrap;
			gap: 10px;
		}

		.media-item {
			position: relative;
			width: calc((100% - 20px) / 3);
			height: 0;
			padding-bottom: calc((100% - 20px) / 3);
			background-color: #f8f8f8;
			border-radius: 8px;
			overflow: hidden;

			image,
			video {
				position: absolute;
				width: 100%;
				height: 100%;
				object-fit: cover;
			}

			.delete-btn {
				position: absolute;
				top: 5px;
				right: 5px;
				width: 20px;
				height: 20px;
				background: rgba(0, 0, 0, 0.5);
				border-radius: 50%;
				display: flex;
				align-items: center;
				justify-content: center;
				z-index: 2;
			}

			.media-mask {
				position: absolute;
				bottom: 0;
				left: 0;
				right: 0;
				height: 30px;
				background: linear-gradient(to top, rgba(0, 0, 0, 0.5), transparent);
				display: flex;
				align-items: center;
				justify-content: center;
				z-index: 1;
			}
		}

		.upload-trigger {
			width: calc((100% - 20px) / 3);
			height: 0;
			padding-bottom: calc((100% - 20px) / 3);
			position: relative;

			.upload-box {
				position: absolute;
				width: 100%;
				height: 100%;
				background-color: #f8f8f8;
				border-radius: 8px;
				display: flex;
				flex-direction: column;
				align-items: center;
				justify-content: center;

				.upload-text {
					margin-top: 5px;
					font-size: 12px;
					color: #999;
				}
			}
		}

		.upload-tip {
			margin-top: 10px;
			font-size: 12px;
			color: #999;
		}
	}
</style>