<script setup lang="ts">
import { useQRCode } from "vue3-next-qrcode"
import "vue3-next-qrcode/es/style.css"

// 二维码生成选项类型
export interface QRCodeGenerateOptions {
	text?: string // 二维码文本内容
	size?: number // 二维码尺寸（像素）
	margin?: number // 二维码边距（像素）
	correctLevel?: 0 | 1 | 2 | 3 // 纠错等级 (0=L, 1=M, 2=Q, 3=H)
	maskPattern?: number // 掩码图案 (0-7)，用于优化二维码图案分布
	version?: number // 二维码版本 (1-40)，控制二维码容量和复杂度
	colorDark?: string // 二维码深色块颜色
	colorLight?: string // 二维码浅色块颜色
	autoColor?: boolean // 是否自动计算浅色值，根据背景智能调整
	logoImage?: string // 中心Logo图片地址
	logoScale?: number // Logo尺寸相对于二维码的比例 (0-1)
	logoMargin?: number // Logo边距（像素）
	logoCornerRadius?: number // Logo圆角半径（像素）
	backgroundImage?: string // 背景图片地址
	backgroundDimming?: string // 背景图片遮罩颜色
	gifBackgroundURL?: string // GIF背景图片地址
	whiteMargin?: boolean // 是否使用白色边距，避免透明背景
	dotScale?: number // 点的缩放比例 (0-1)，默认 1，越小定位点越精致
}

const props = withDefaults(
	defineProps<{
		modelValue?: string // 二维码文本内容
		title?: string // 标题文本
		titlePosition?: "top" | "bottom" // 标题位置：上方或下方
		titleStyle?: object // 标题自定义样式
		size?: number // 二维码尺寸（像素）
		margin?: number // 二维码边距（像素）
		colorDark?: string // 二维码深色块颜色
		colorLight?: string // 二维码浅色块颜色
		correctLevel?: 0 | 1 | 2 | 3 // 纠错等级 (0=L, 1=M, 2=Q, 3=H)
		logoImage?: string // 中心Logo图片地址
		logoScale?: number // Logo尺寸相对于二维码的比例
		logoMargin?: number // Logo边距（像素）
		logoCornerRadius?: number // Logo圆角半径（像素）
		backgroundImage?: string // 背景图片地址
		backgroundDimming?: string // 背景图片遮罩颜色
		gifBackgroundURL?: string // GIF背景图片地址
		whiteMargin?: boolean // 是否使用白色边距
		autoColor?: boolean // 是否自动计算浅色值
		dotScale?: number // 点的缩放比例 (0-1)，默认 1，越小定位点越小
		loadingText?: string // 加载提示文本
		errorText?: string // 错误提示文本
	}>(),
	{
		modelValue: "",
		title: "",
		titlePosition: "top",
		titleStyle: undefined,
		size: 200,
		margin: 12,
		colorDark: "#000000",
		colorLight: "#ffffff",
		correctLevel: 1,
		logoImage: undefined,
		logoScale: 0.4,
		logoMargin: 6,
		logoCornerRadius: 8,
		backgroundImage: undefined,
		backgroundDimming: "rgba(0, 0, 0, 0)",
		gifBackgroundURL: undefined,
		whiteMargin: true,
		autoColor: true,
		dotScale: 1, // 默认减小定位点大小
		loadingText: "生成中...",
		errorText: "生成失败"
	}
)

const emits = defineEmits<{
	(e: "update:modelValue", v: string): void
	(e: "success", dataURL: ArrayBuffer | string | undefined): void
	(e: "error", error: unknown): void
}>()

// 使用 useQRCode Composable
const { qrcodeURL, isLoading, error: qrError, generate, clear } = useQRCode()

/**
 * 生成二维码（暴露给父组件调用）
 * @param options 二维码配置选项
 * @returns Promise，成功时解析为 dataURL
 */
function generateQRCode(
	options?: QRCodeGenerateOptions
): Promise<ArrayBuffer | string | undefined> {
	// 如果传入了 text 则使用传入的，否则使用 modelValue
	const textToUse = options?.text !== undefined ? options.text : props.modelValue

	if (!textToUse) {
		console.warn("VbQrGen：未提供二维码文本内容")
		const error = new Error("未提供二维码文本内容")
		emits("error", error)
		return Promise.reject(error)
	}

	return generate({
		text: textToUse,
		size: options?.size ?? props.size,
		margin: options?.margin ?? props.margin,
		correctLevel: options?.correctLevel ?? props.correctLevel,
		maskPattern: options?.maskPattern,
		version: options?.version,
		colorDark: options?.colorDark ?? props.colorDark,
		colorLight: options?.colorLight ?? props.colorLight,
		autoColor: options?.autoColor ?? props.autoColor,
		logoImage: options?.logoImage ?? props.logoImage,
		logoScale: options?.logoScale ?? props.logoScale,
		logoMargin: options?.logoMargin ?? props.logoMargin,
		logoCornerRadius: options?.logoCornerRadius ?? props.logoCornerRadius,
		backgroundImage: options?.backgroundImage ?? props.backgroundImage,
		backgroundDimming: options?.backgroundDimming ?? props.backgroundDimming,
		gifBackgroundURL: options?.gifBackgroundURL ?? props.gifBackgroundURL,
		whiteMargin: options?.whiteMargin ?? props.whiteMargin,
		dotScale: options?.dotScale ?? props.dotScale
	})
		.then((dataURL) => {
			// 将返回值转换为 emits 期望的类型
			const result = dataURL as ArrayBuffer | string | undefined
			emits("success", result)
			return result
		})
		.catch((error) => {
			console.error("VbQrGen：二维码生成失败", error)
			emits("error", error)
			throw error
		})
}

/**
 * 清除二维码
 */
function clearQRCode() {
	clear()
}

/**
 * 下载二维码图片
 * @param fileName 文件名（不含扩展名），默认为 'qrcode'
 * @returns Promise
 */
function downloadQRCode(fileName: string = "qrcode"): Promise<void> {
	return new Promise((resolve, reject) => {
		try {
			const dataURL = qrcodeURL.value
			if (!dataURL || typeof dataURL !== "string") {
				const error = new Error("VbQrGen：二维码数据未生成")
				console.error(error.message)
				reject(error)
				return
			}

			// 创建下载链接
			const link = document.createElement("a")
			link.href = dataURL
			link.download = `${fileName}.png`
			document.body.appendChild(link)
			link.click()
			document.body.removeChild(link)

			console.log("VbQrGen：二维码下载成功")
			resolve()
		} catch (error) {
			console.error("VbQrGen：二维码下载失败", error)
			reject(error)
		}
	})
}

/**
 * 打印二维码图片
 * @param title 打印标题,默认为使用组件的 title prop 或 '二维码'
 * @returns Promise
 */
function printQRCode(title?: string): Promise<void> {
	return new Promise((resolve, reject) => {
		try {
			// 使用 Composable 生成的 qrcodeURL
			const dataURL = qrcodeURL.value
			if (!dataURL || typeof dataURL !== "string") {
				const error = new Error("VbQrGen:二维码数据未生成")
				console.error(error.message)
				reject(error)
				return
			}

			// 确定打印标题：优先使用传入的 title，其次使用 props.title，最后使用默认值
			const printTitle = title || props.title || "二维码"

			// 尝试获取自定义插槽内容用于打印（优先使用 ref，降级为 querySelector）
			const contentContainer = contentRef.value || document.querySelector(".vb-qr-content")
			let customContentHTML = ""

			if (contentContainer) {
				// 克隆节点以获取当前显示的内容（包括自定义插槽）
				const clonedContent = contentContainer.cloneNode(true) as HTMLElement
				customContentHTML = clonedContent.innerHTML
			}

			// 创建打印窗口
			const printWindow = window.open("", "_blank")
			if (!printWindow) {
				const error = new Error("VbQrGen:无法打开打印窗口,请检查浏览器弹窗设置")
				console.error(error.message)
				reject(error)
				return
			}

			// 构建打印页面内容（不使用 script 标签，改用 onload 属性）
			const printContent = `
				<!DOCTYPE html>
				<html>
				<head>
					<meta charset="UTF-8">
					<title>${printTitle}</title>
					<style>
						* {
							margin: 0;
							padding: 0;
							box-sizing: border-box;
						}
						body {
							display: flex;
							flex-direction: column;
							justify-content: center;
							align-items: center;
							min-height: 100vh;
							padding: 20px;
							font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
						}
						.title {
							font-size: 24px;
							font-weight: bold;
							margin-bottom: 20px;
							color: #333;
							text-align: center;
						}
						.qrcode-container {
							display: flex;
							justify-content: center;
							align-items: center;
							margin: 20px 0;
						}
						.qrcode-image {
							max-width: 100%;
							height: auto;
						}
						@media print {
							body {
								print-color-adjust: exact;
								-webkit-print-color-adjust: exact;
							}
						}
					</style>
				</head>
				<body onload="setTimeout(function() { window.print(); setTimeout(function() { window.close(); }, 100); }, 500)">
					<div class="title">${printTitle}</div>
					<div class="qrcode-container">
						${customContentHTML || `<img src="${dataURL}" alt="二维码" class="qrcode-image" />`}
					</div>
				</body>
				</html>
			`

			// 使用 Blob 和 URL.createObjectURL 替代已弃用的 document.write
			const blob = new Blob([printContent], { type: "text/html;charset=utf-8" })
			const url = URL.createObjectURL(blob)
			printWindow.location.href = url

			console.log("VbQrGen:二维码打印窗口已打开")
			resolve()
		} catch (error) {
			console.error("VbQrGen:二维码打印失败", error)
			reject(error)
		}
	})
}

/**
 * 获取二维码 Data URL
 * @returns Data URL 字符串或 null
 */
function getQRCodeDataURL(): string | null {
	try {
		const dataURL = qrcodeURL.value
		if (!dataURL || typeof dataURL !== "string") {
			console.warn("VbQrGen：二维码数据未生成")
			return null
		}
		return dataURL
	} catch (error) {
		console.error("VbQrGen：获取二维码 Data URL 失败", error)
		return null
	}
}

// 标题样式
const titleStyle = computed(() => {
	const defaultStyle: Record<string, string> = {
		fontSize: "16px",
		fontWeight: "bold",
		color: "#333",
		marginBottom: props.titlePosition === "top" ? "12px" : "0",
		marginTop: props.titlePosition === "bottom" ? "12px" : "0",
		textAlign: "center"
	}
	return {
		...defaultStyle,
		...(props.titleStyle || {})
	}
})

// 内容容器引用（用于打印时获取自定义插槽内容）
const contentRef = ref<HTMLElement | null>(null)

// 暴露方法给父组件
defineExpose({
	// 核心方法
	generateQRCode,
	clearQRCode,
	downloadQRCode,
	printQRCode,
	getQRCodeDataURL,
	// 状态获取方法（不直接暴露内部状态）
	getQRCodeState() {
		return {
			url: qrcodeURL.value,
			loading: isLoading.value,
			error: qrError.value
		}
	}
})
</script>

<template>
	<div class="vb-qr-gen">
		<!-- 标题在上方 -->
		<template v-if="props.title && props.titlePosition === 'top'">
			<!-- 使用插槽自定义标题 -->
			<slot v-if="$slots.title" name="title"></slot>
			<!-- 使用默认标题 -->
			<div v-else class="vb-qr-title" :style="titleStyle">{{ props.title }}</div>
		</template>

		<!-- 二维码图片 -->
		<div v-if="qrcodeURL && typeof qrcodeURL === 'string'" ref="contentRef" class="vb-qr-content">
			<!-- 使用插槽自定义二维码显示 -->
			<slot v-if="$slots.qrcode" name="qrcode" :qrcode-url="qrcodeURL" :size="props.size"></slot>
			<!-- 默认显示图片 -->
			<img
				v-else
				:src="qrcodeURL"
				alt="二维码"
				class="vb-qr-image"
				:style="{ width: props.size + 'px', height: props.size + 'px' }" />
		</div>
		<!-- 加载中状态 -->
		<div v-else-if="isLoading" class="vb-qr-content">
			<!-- 使用插槽自定义加载状态 -->
			<slot v-if="$slots.loading" name="loading"></slot>
			<!-- 默认加载提示 -->
			<template v-else>
				<div class="vb-qr-spinner"></div>
				<span>{{ loadingText }}</span>
			</template>
		</div>
		<!-- 错误状态 -->
		<div v-else-if="qrError" class="vb-qr-content">
			<!-- 使用插槽自定义错误状态 -->
			<slot v-if="$slots.error" name="error" :error="qrError"></slot>
			<!-- 默认错误提示 -->
			<template v-else>
				<span>{{ errorText }}</span>
			</template>
		</div>

		<!-- 标题在下方 -->
		<template v-if="props.title && props.titlePosition === 'bottom'">
			<!-- 使用插槽自定义标题 -->
			<slot v-if="$slots.title" name="title"></slot>
			<!-- 使用默认标题 -->
			<div v-else class="vb-qr-title" :style="titleStyle">{{ props.title }}</div>
		</template>
	</div>
</template>

<style scoped lang="scss">
.vb-qr-gen {
	display: inline-flex;
	flex-direction: column;
	justify-content: center;
	align-items: center;

	.vb-qr-title {
		width: 100%;
	}

	.vb-qr-content {
		display: flex;
		justify-content: center;
		align-items: center;
	}

	.vb-qr-image {
		display: block;
		object-fit: contain;
	}

	.vb-qr-spinner {
		width: 30px;
		height: 30px;
		border: 3px solid #e5e7eb;
		border-top-color: #1677ff;
		border-radius: 50%;
		animation: spin 0.75s linear infinite;
	}

	@keyframes spin {
		to {
			transform: rotate(360deg);
		}
	}
}
</style>
