<template>
    <view class="qr-container">
        <canvas :id="canvasId" :canvas-id="canvasId" class="qr-canvas" :width="width" :height="height" :style="{
            width: width + 'px',
            height: height + 'px'
        }" />
    </view>
</template>

<script setup>
import { onMounted, watch } from 'vue'
import QRCode from 'qrcode'

// TextEncoder polyfill for uni-app
if (typeof TextEncoder === 'undefined') {
    globalThis.TextEncoder = class TextEncoder {
        encode(str) {
            const buf = new ArrayBuffer(str.length)
            const bufView = new Uint8Array(buf)
            for (let i = 0, strLen = str.length; i < strLen; i++) {
                bufView[i] = str.charCodeAt(i)
            }
            return bufView
        }
    }
}

// TextDecoder polyfill for uni-app
if (typeof TextDecoder === 'undefined') {
    globalThis.TextDecoder = class TextDecoder {
        decode(uint8arr) {
            let encodedString = String.fromCharCode.apply(null, uint8arr)
            let decodedString = decodeURIComponent(escape(encodedString))
            return decodedString
        }
    }
}

const props = defineProps({
    /** 二维码内容 */
    text: {
        type: String,
        required: true
    },
    /** 宽高 */
    width: {
        type: Number,
        default: 200
    },
    height: {
        type: Number,
        default: 200
    },
    /** 颜色 */
    colorDark: {
        type: String,
        default: '#000000'
    },
    colorLight: {
        type: String,
        default: '#ffffff'
    },
    /** 中间 logo（可选） */
    logo: {
        type: String,
        default: ''
    },
    /** logo 占比 */
    logoScale: {
        type: Number,
        default: 0.22
    }
})
const canvasId = `qr_${Date.now()}`

/** 绘制二维码 */
async function drawQr() {
    console.log('开始绘制二维码:', props.text)
    if (!props.text) {
        console.warn('二维码文本为空')
        return
    }

    try {
        // 延迟确保canvas已初始化
        await new Promise(resolve => setTimeout(resolve, 100))

        const res = await QRCode.create(props.text, {
            errorCorrectionLevel: 'H'
        })

        // 获取canvas上下文
        const ctx = uni.createCanvasContext(canvasId)
        if (!ctx) {
            console.error('无法获取canvas上下文')
            return
        }

        const size = props.width
        const count = res.modules.size
        const cellSize = size / count

        // 背景
        ctx.setFillStyle(props.colorLight)
        ctx.fillRect(0, 0, size, size)

        // 绘制二维码
        for (let row = 0; row < count; row++) {
            for (let col = 0; col < count; col++) {
                ctx.setFillStyle(
                    res.modules.get(row, col)
                        ? props.colorDark
                        : props.colorLight
                )
                ctx.fillRect(
                    col * cellSize,
                    row * cellSize,
                    Math.ceil(cellSize),
                    Math.ceil(cellSize)
                )
            }
        }

        // 绘制到canvas
        ctx.draw(false, () => {
            console.log('二维码绘制成功')
            // 绘制 logo
            if (props.logo) {
                drawLogo(ctx)
            }
        })
    } catch (e) {
        console.error('二维码绘制错误:')
        console.error('错误类型:', e.constructor.name)
        console.error('错误信息:', e.message)
        console.error('错误堆栈:', e.stack)
        uni.showToast({
            title: '二维码生成失败',
            icon: 'none',
            duration: 2000
        })
    }
}

/** 绘制中间 logo */
function drawLogo(ctx) {
    const size = props.width
    const logoSize = size * props.logoScale
    const dx = (size - logoSize) / 2
    const dy = (size - logoSize) / 2

    // 绘制白色背景
    ctx.setFillStyle('#ffffff')
    ctx.fillRect(dx - 5, dy - 5, logoSize + 10, logoSize + 10)

    // 在真机上，确保图片已加载再绘制
    const img = new Image()
    img.src = props.logo
    img.onload = () => {
        ctx.drawImage(props.logo, dx, dy, logoSize, logoSize)
        ctx.draw(true)
    }
    img.onerror = () => {
        console.error('Logo图片加载失败:', props.logo)
    }
}

/** 下载二维码 */
function download() {
    uni.canvasToTempFilePath({
        canvasId,
        success(res) {
            console.log('canvas转图片成功:', res.tempFilePath)
            uni.saveImageToPhotosAlbum({
                filePath: res.tempFilePath,
                success() {
                    uni.showToast({ title: '已保存', icon: 'success' })
                },
                fail(err) {
                    console.error('保存图片失败:', err)
                    uni.showToast({ title: '保存失败', icon: 'error' })
                }
            })
        },
        fail(err) {
            console.error('canvas转图片失败:', err)
            uni.showToast({ title: '生成图片失败', icon: 'error' })
        }
    })
}

onMounted(() => {
    console.log('QrCode组件已挂载，准备绘制二维码')
    drawQr()
})

watch(() => props.text, () => {
    console.log('二维码文本变化，重新绘制:', props.text)
    drawQr()
})

defineExpose({
    download
})
</script>

<style scoped lang="scss">
@import "@/uni.scss";

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

.qr-canvas {
    background: transparent;
}
</style>
