/**
 * 名片海报生成工具
 * 使用 Canvas 手动绘制名片
 */

/**
 * 生成名片海报
 * @param {Object} options - 配置选项
 * @param {Object} options.cardInfo - 名片信息
 * @returns {Promise<String>} - 生成的图片临时路径
 */
export const generateCardPoster = async (cardInfo) => {
	return new Promise((resolve, reject) => {
		try {
			// 创建离屏 canvas
			const query = uni.createSelectorQuery()
			query.select('#posterCanvas')
				.fields({
					node: true,
					size: true
				})
				.exec(async (res) => {
					if (!res[0]) {
						reject(new Error('Canvas 节点未找到'))
						return
					}

					const canvas = res[0].node
					const ctx = canvas.getContext('2d')

					// 设置 canvas 尺寸（高分辨率）
					const width = 750
					const height = 800
					const dpr = uni.getSystemInfoSync().pixelRatio

					canvas.width = width * dpr
					canvas.height = height * dpr
					ctx.scale(dpr, dpr)

					// 1. 绘制背景渐变
					const gradient = ctx.createLinearGradient(0, 0, 0, height)
					gradient.addColorStop(0, '#4A90E2')
					gradient.addColorStop(0.5, '#6FB3F2')
					gradient.addColorStop(1, '#87CEEB')
					ctx.fillStyle = gradient
					ctx.fillRect(0, 0, width, height)

					// 2. 绘制白色卡片背景
					ctx.fillStyle = '#ffffff'
					drawRoundRect(ctx, 40, 40, 670, 720, 24)
					ctx.fill()

					// 3. 绘制头像
					const avatarPath = cardInfo.avatar ||
						'/static/image/public/avatar-default.png'
					await drawAvatar(ctx, avatarPath, 375, 160, 160)

					// 4. 绘制姓名和职位
					ctx.fillStyle = '#202020'
					ctx.font = 'bold 44px sans-serif'
					ctx.textAlign = 'center'
					ctx.fillText(cardInfo.nickName || '用户', width / 2, 380)

					// 职位标签背景
					ctx.fillStyle = 'rgba(68, 110, 255, 0.1)'
					drawRoundRect(ctx, (width - 180) / 2, 400, 180, 44, 8)
					ctx.fill()

					ctx.fillStyle = '#446eff'
					ctx.font = '26px sans-serif'
					ctx.textAlign = 'center'
					ctx.fillText(cardInfo.postName || '职位', width / 2, 430)

					// 5. 绘制公司名称
					ctx.fillStyle = '#666666'
					ctx.font = '30px sans-serif'
					ctx.textAlign = 'center'
					wrapText(ctx, cardInfo.companyName || '公司名称', width / 2, 480, 500, 36)

					// 6. 绘制联系方式
					const contactY = 560
					const contactGap = 65
					ctx.textAlign = 'left'
					// 电话
					if (cardInfo.phonenumber) {
						await drawIconText(ctx, 'phone', cardInfo.phonenumber, width / 2 - 130,
							contactY)
					}

					// 邮箱
					if (cardInfo.email) {
						await drawIconText(ctx, 'email', cardInfo.email, width / 2 - 130,
							contactY + contactGap)
					}

					// 地址
					if (cardInfo.companyAddress) {
						await drawIconText(ctx, 'location', cardInfo.companyAddress, width / 2 -
							130, contactY + contactGap * 2, )
					}

					// 导出图片
					setTimeout(() => {
						uni.canvasToTempFilePath({
							canvas: canvas,
							success: (res) => {
								console.log('海报生成成功:', res.tempFilePath)
								resolve(res.tempFilePath)
							},
							fail: (err) => {
								console.error('海报导出失败:', err)
								reject(err)
							}
						})
					}, 300)
				})
		} catch (error) {
			console.error('海报生成失败:', error)
			reject(error)
		}
	})
}

/**
 * 绘制圆角矩形（兼容微信小程序）
 */
const drawRoundRect = (ctx, x, y, width, height, radius) => {
	ctx.beginPath()
	ctx.moveTo(x + radius, y)
	ctx.lineTo(x + width - radius, y)
	ctx.quadraticCurveTo(x + width, y, x + width, y + radius)
	ctx.lineTo(x + width, y + height - radius)
	ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height)
	ctx.lineTo(x + radius, y + height)
	ctx.quadraticCurveTo(x, y + height, x, y + height - radius)
	ctx.lineTo(x, y + radius)
	ctx.quadraticCurveTo(x, y, x + radius, y)
	ctx.closePath()
}

/**
 * 绘制头像
 */
const drawAvatar = async (ctx, avatarUrl, x, y, size) => {
	return new Promise((resolve) => {
		if (avatarUrl.startsWith('http')) {
			// 网络图片
			downloadAndDraw(ctx, avatarUrl, x, y, size, resolve)
		} else {
			drawCircularImage(ctx, avatarUrl, x, y, size, resolve)
		}
	})
}

/**
 * 下载并绘制网络图片
 */
const downloadAndDraw = async (ctx, url, x, y, size, resolve) => {
	try {
		const res = await uni.downloadFile({
			url: url
		})

		if (res.statusCode === 200) {
			drawCircularImage(ctx, res.tempFilePath, x, y, size, resolve)
		} else {
			console.error('图片下载失败:', res.statusCode)
			resolve()
		}
	} catch (error) {
		console.error('下载图片异常:', error)
		resolve()
	}
}

/**
 * 绘制圆形图片
 */
const drawCircularImage = (ctx, imageUrl, x, y, size, callback) => {
	const image = uni.createImage()
	image.src = imageUrl
	image.onload = () => {
		ctx.save()
		ctx.beginPath()
		ctx.arc(x, y, size / 2, 0, 2 * Math.PI)
		ctx.clip()
		ctx.drawImage(image, x - size / 2, y - size / 2, size, size)
		ctx.restore()
		if (callback) callback()
	}
	image.onerror = (err) => {
		console.error('图片加载失败:', err)
		if (callback) callback()
	}
}

/**
 * 绘制图标和文字
 */
const drawIconText = async (ctx, type, text, x, y, maxWidth = 350) => {
	return new Promise((resolve) => {
		const iconSize = 32
		const iconY = y - iconSize / 2

		// 图标颜色
		const iconColors = {
			phone: '#4080FF',
			email: '#4080FF',
			location: '#4080FF'
		}

		ctx.fillStyle = iconColors[type] || '#4080FF'

		// 绘制图标
		const icons = {
			phone: '',
			email: '',
			location: ''
		}

		ctx.font = `${iconSize}px sans-serif`
		ctx.textAlign = 'center'
		ctx.fillText(icons[type] || '●', x - maxWidth / 2 + 30, iconY + iconSize / 2 + 10)

		// 绘制文字
		ctx.fillStyle = '#666666'
		ctx.font = '26px sans-serif'
		ctx.textAlign = 'left'

		// 文字截断处理
		let displayText = text
		if (text.length > 35) {
			displayText = text.substring(0, 33) + '...'
		}
		ctx.fillText(displayText, x - maxWidth / 2 + 70, y + 8)

		setTimeout(resolve, 50)
	})
}

/**
 * 绘制换行文字
 */
const wrapText = (ctx, text, x, y, maxWidth, lineHeight) => {
	if (!text) return

	const words = text.split('')
	let line = ''
	let currentY = y

	for (let i = 0; i < words.length; i++) {
		const testLine = line + words[i]
		const metrics = ctx.measureText(testLine)

		if (metrics.width > maxWidth && i > 0) {
			ctx.fillText(line, x, currentY)
			line = words[i]
			currentY += lineHeight
		} else {
			line = testLine
		}
	}
	ctx.fillText(line, x, currentY)
}

/**
 * 保存海报到相册
 */
export const savePosterToAlbum = async (tempFilePath) => {
	return new Promise((resolve, reject) => {
		uni.authorize({
			scope: 'scope.writePhotosAlbum',
			success: async () => {
				uni.saveImageToPhotosAlbum({
					filePath: tempFilePath,
					success: () => resolve(),
					fail: (err) => reject(err)
				})
			},
			fail: (err) => {
				uni.showModal({
					title: '提示',
					content: '需要授权才能保存到相册',
					success: (res) => {
						if (res.confirm) {
							uni.openSetting({
								success: (settingRes) => {
									if (settingRes.authSetting[
											'scope.writePhotosAlbum'
											]) {
										savePosterToAlbum(
											tempFilePath).then(
											resolve).catch(
											reject)
									} else {
										reject(new Error('用户拒绝授权'))
									}
								},
								fail: (err) => reject(err)
							})
						} else {
							reject(new Error('用户取消授权'))
						}
					}
				})
			}
		})
	})
}

export default {
	generateCardPoster,
	savePosterToAlbum
}