<template>
	<view class="popup-container" v-if="value" @click="close">
		<view class="popup-wrapper">
			<view class="popup-title" v-if="showTitle">您已经成为亿职赞第{{ rank }}位金牌推荐官</view>
			<view class="poster-wrapper">
				<image :src="posterImageSrc" class="poster-img" mode="aspectFit"></image>
			</view>
			<view class="poster-tip" v-if="showTip">推荐者的个人信息不会公开展示，请放心推荐</view>
			<view class="button" @click.stop="handleSave">{{ saveBtnText }}</view>
		</view>
	</view>
</template>

<script>
	export default {
		props: {
			value: {
				type: Boolean,
				default: false
			},
			rank: {
				type: Number,
				default: 0
			},
			posterBase64Url: {
				type: String,
				default: ''
			},
			/** 纯 base64 时的图片类型，默认 png；若后端是 jpeg 可传 image/jpeg */
			posterMime: {
				type: String,
				default: 'image/png'
			},
			showTitle: {
				type: Boolean,
				default: true
			},
			showTip: {
				type: Boolean,
				default: true
			},
			saveBtnText: {
				type: String,
				default: '保存海报并成为推荐官'
			},
		},
		computed: {
			posterImageSrc() {
				const raw = this.posterBase64Url
				if (!raw || typeof raw !== 'string') return ''
				const t = raw.trim()
				if (
					t.startsWith('data:image') ||
					t.startsWith('http://') ||
					t.startsWith('https://') ||
					t.startsWith('/') ||
					t.startsWith('@/')
				) {
					return t
				}
				// 去掉换行空格，拼成 data URL 供 image 显示
				const b64 = t.replace(/\s/g, '')
				return `data:${this.posterMime};base64,${b64}`
			}
		},
		data() {
			return {
				num: 990
			}
		},
		methods: {
			close() {
				this.$emit('close')
			},
			
			handleSave() {
				const src = this.posterImageSrc
				if (!src) {
					uni.showToast({ title: '暂无海报', icon: 'none' })
					return
				}
				// #ifdef H5
				this._savePosterH5(src)
				// #endif
				// #ifdef APP-PLUS
				this._savePosterApp(src)
				// #endif
			},

			// #ifdef H5
			_savePosterH5(src) {
				if (src.startsWith('data:image')) {
					try {
						const parts = src.split(',')
						const mimeMatch = parts[0].match(/:(.*?);/)
						const mime = mimeMatch ? mimeMatch[1] : 'image/png'
						const bstr = atob(parts[1])
						const n = bstr.length
						const u8arr = new Uint8Array(n)
						for (let i = 0; i < n; i++) u8arr[i] = bstr.charCodeAt(i)
						const blob = new Blob([u8arr], { type: mime })
						const url = URL.createObjectURL(blob)
						const a = document.createElement('a')
						a.href = url
						a.download = 'poster.' + (mime.indexOf('jpeg') !== -1 ? 'jpg' : 'png')
						document.body.appendChild(a)
						a.click()
						document.body.removeChild(a)
						URL.revokeObjectURL(url)
						uni.showToast({ title: '已开始下载' })
						this.$emit('saved')
					} catch (e) {
						uni.showToast({ title: '保存失败', icon: 'none' })
					}
					return
				}
				if (src.startsWith('http://') || src.startsWith('https://')) {
					uni.showLoading({ title: '保存中...', mask: true })
					fetch(src, { mode: 'cors' })
						.then((res) => {
							if (!res.ok) throw new Error('fetch fail')
							return res.blob()
						})
						.then((blob) => {
							uni.hideLoading()
							const url = URL.createObjectURL(blob)
							const a = document.createElement('a')
							a.href = url
							a.download = 'poster.png'
							document.body.appendChild(a)
							a.click()
							document.body.removeChild(a)
							URL.revokeObjectURL(url)
							uni.showToast({ title: '已开始下载' })
							this.$emit('saved')
						})
						.catch(() => {
							uni.hideLoading()
							uni.showToast({
								title: '无法下载，请长按图片保存',
								icon: 'none'
							})
						})
					return
				}
				uni.showToast({ title: '请使用网络图或 base64 图片', icon: 'none' })
			},
			// #endif

			// #ifdef APP-PLUS
			/**
			 * App 保存难在：① 相册权限各版本 Android 规则不同，误检会拦死；② saveImageToPhotosAlbum 多数机型要传 _doc/相对路径而非乱转 file://。
			 * 这里按 DCloud 文档最小路径：Bitmap → _doc/xxx.png → uni.saveImageToPhotosAlbum（先试相对路径）。
			 */
			async _savePosterApp(src) {
				const allowed = await this._ensureAlbumPermissionForSave()
				if (!allowed) return

				uni.showLoading({ title: '保存中...', mask: true })
				const hide = () => {
					try {
						uni.hideLoading()
					} catch (e) {}
				}

				try {
					await this._withTimeout(this._savePosterAppCore(src), 50000, '保存超时，请重试')
					hide()
					uni.showToast({ title: '已保存到相册', icon: 'success' })
					this.$emit('saved')
				} catch (e) {
					hide()
					const msg = String((e && (e.errMsg || e.message)) || '保存失败')
					if (/auth|permission|denied|拒绝|authorize/i.test(msg)) {
						this._openAlbumSettingsModal()
					} else {
						uni.showToast({ title: msg.length > 36 ? '保存失败' : msg, icon: 'none' })
					}
				}
			},

			_withTimeout(p, ms, errMsg) {
				return Promise.race([
					Promise.resolve(p),
					new Promise((_, reject) =>
						setTimeout(() => reject(new Error(errMsg || '操作超时')), ms)
					)
				])
			},

			async _savePosterAppCore(src) {
				let local = ''
				if (src.startsWith('data:image')) {
					local = await this._bitmapDataUrlToDocRel(src)
				} else if (src.startsWith('http://') || src.startsWith('https://')) {
					local = await new Promise((resolve, reject) => {
						uni.downloadFile({
							url: src,
							success: (r) => {
								if (r.statusCode === 200 && r.tempFilePath) resolve(r.tempFilePath)
								else reject(new Error('图片下载失败'))
							},
							fail: () => reject(new Error('图片下载失败'))
						})
					})
				} else {
					local = src
				}
				await this._saveImageToAlbumTryPaths(this._albumPathCandidates(local))
			},

			/** 官方示例：loadBase64Data → save 到 _doc，返回相对路径 */
			_bitmapDataUrlToDocRel(dataUrl) {
				return new Promise((resolve, reject) => {
					const name = 'poster_' + Date.now() + '.png'
					const rel = '_doc/' + name
					const id = 'posterBitmap' + Date.now()
					const bm = new plus.nativeObj.Bitmap(id)
					bm.loadBase64Data(
						dataUrl,
						() => {
							bm.save(
								rel,
								{ overwrite: true },
								() => {
									try {
										bm.clear()
									} catch (e) {}
									resolve(rel)
								},
								(err) => {
									try {
										bm.clear()
									} catch (e) {}
									reject(err || new Error('生成临时图失败'))
								}
							)
						},
						(err) => {
							try {
								bm.clear()
							} catch (e) {}
							reject(err || new Error('图片无法解析'))
						}
					)
				})
			},

			_albumPathCandidates(p) {
				const list = []
				const add = (x) => {
					if (x && list.indexOf(x) === -1) list.push(x)
				}
				add(p)
				if (p && p.startsWith('file://')) {
					add(p.replace(/^file:\/\//, ''))
				}
				if (typeof plus !== 'undefined' && plus.io && p) {
					try {
						add(plus.io.convertLocalFileSystemURL(p))
					} catch (e) {}
				}
				return list
			},

			_saveImageToAlbumTryPaths(paths) {
				if (!paths.length) {
					return Promise.reject(new Error('没有可保存的路径'))
				}
				return paths.reduce(
					(acc, fp) =>
						acc.catch(() =>
							new Promise((resolve, reject) => {
								uni.saveImageToPhotosAlbum({
									filePath: fp,
									success: () => resolve(),
									fail: (err) => reject(err || new Error('保存失败'))
								})
							})
						),
					Promise.reject(new Error('_'))
				)
			},

			_openAlbumSettingsModal() {
				uni.showModal({
					title: '需要相册权限',
					content: '保存图片到相册需要相册/存储权限，请在系统设置中开启后重试。',
					confirmText: '去设置',
					cancelText: '取消',
					success: (r) => {
						if (r.confirm && typeof uni.openAppAuthorizeSetting === 'function') {
							uni.openAppAuthorizeSetting({})
						}
					}
				})
			},

			/** 是否具备保存到相册所需权限；否：已弹窗引导，返回 false */
			_ensureAlbumPermissionForSave() {
				return new Promise((resolve) => {
					if (typeof plus === 'undefined') {
						resolve(true)
						return
					}
					const os = plus.os.name
					if (os === 'iOS') {
						resolve(this._ensureIosAlbumPermissionForSave())
						return
					}
					if (os === 'Android') {
						this._ensureAndroidAlbumPermissionForSave().then(resolve)
						return
					}
					resolve(true)
				})
			},

			_ensureIosAlbumPermissionForSave() {
				try {
					if (typeof uni.getAppAuthorizeSetting !== 'function') {
						return true
					}
					const s = uni.getAppAuthorizeSetting() || {}
					const a = s.albumAuthorized
					if (a === 'authorized' || a === 'limited') {
						return true
					}
					if (a === 'denied') {
						this._openAlbumSettingsModal()
						return false
					}
					// not determined / 未返回：首次保存时由系统弹窗授权
					return true
				} catch (e) {
					return true
				}
			},

			_androidCheckPermissions(permissions) {
				try {
					const main = plus.android.runtimeMainActivity()
					const PM = plus.android.importClass('android.content.pm.PackageManager')
					const granted = PM.PERMISSION_GRANTED
					for (let i = 0; i < permissions.length; i++) {
						if (main.checkSelfPermission(permissions[i]) !== granted) {
							return false
						}
					}
					return true
				} catch (e) {
					return false
				}
			},

			/**
			 * Android 10+ 分区存储下，写入相册多走系统 MediaStore，预检 READ_MEDIA_IMAGES 常误判且与「保存」无关，会导致永远进不了保存。
			 * 仅对 Android 9 及以下尝试申请 WRITE_EXTERNAL_STORAGE；其余交给 saveImageToPhotosAlbum 与系统弹窗。
			 */
			_ensureAndroidAlbumPermissionForSave() {
				return new Promise((resolve) => {
					if (!plus.android) {
						resolve(true)
						return
					}
					try {
						const Build = plus.android.importClass('android.os.Build')
						if (Build.VERSION.SDK_INT >= 29) {
							resolve(true)
							return
						}
						if (Build.VERSION.SDK_INT < 23) {
							resolve(true)
							return
						}
					} catch (e) {
						resolve(true)
						return
					}
					if (typeof plus.android.requestPermissions !== 'function') {
						resolve(true)
						return
					}
					const perms = ['android.permission.WRITE_EXTERNAL_STORAGE']
					if (this._androidCheckPermissions(perms)) {
						resolve(true)
						return
					}
					plus.android.requestPermissions(
						perms,
						() => {
							if (this._androidCheckPermissions(perms)) {
								resolve(true)
							} else {
								this._openAlbumSettingsModal()
								resolve(false)
							}
						},
						() => {
							this._openAlbumSettingsModal()
							resolve(false)
						}
					)
				})
			},
			// #endif
		}
	}
</script>

<style lang="scss" scoped>
	.popup-container {
		position: fixed;
		left: 0;
		top: 0;
		width: 100vw;
		height: 100vh;
		background: rgba(0, 0, 0, 0.6);
		display: flex;
		align-items: center;
		justify-content: center;
		.popup-wrapper {
			.popup-title {
				color: rgba(255, 255, 255, 1);
				font-style: Bold;
				font-size: 40rpx;
				font-weight: 700;
				line-height: 1.6;
			}
			.poster-wrapper {
				width: 488rpx;
				height: 1028rpx;
				border-radius: 20rpx;
				margin: 64rpx auto 32rpx;
				.poster-img {
					width: 100%;
					height: 100%;
				}
			}
			.poster-tip {
				color: rgba(255, 255, 255, 1);
				font-size: 24rpx;
				font-weight: 400;
				line-height: 40rpx;
				text-align: center;
			}
			.button {
				border-radius: 126px;
				background: rgba(255, 255, 255, 1);
				margin: 24rpx 30rpx;
				text-align: center;
				line-height: 90rpx;
				color: rgba(0, 0, 0, 1);
				font-size: 32rpx;
				font-weight: 400;
			}
		}
	}
</style>