<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, dy, logoSize, logoSize)

    // #ifdef H5
    // H5端可直接用图片url
    ctx.drawImage(props.logo, dx, dy, logoSize, logoSize)
    ctx.draw(true)
    // #endif

    // #ifndef H5
    // 小程序/APP端需先下载图片到本地再绘制
    uni.getImageInfo({
        src: props.logo,
        success(res) {
            ctx.drawImage(res.path, dx, dy, logoSize, logoSize)
            ctx.draw(true)
        },
        fail() {
            console.error('Logo图片加载失败:', props.logo)
        }
    })
    // #endif
}
/** 下载二维码 */
function download() {
    // 延迟一点时间确保画布渲染完成
    setTimeout(() => {
        uni.canvasToTempFilePath({
            canvasId: canvasId,
            success(res) {
                console.log('canvas转图片成功:', res.tempFilePath)
                // #ifdef H5
                // H5端下载处理
                const a = document.createElement('a')
                a.href = res.tempFilePath
                a.download = 'qrcode.png'
                document.body.appendChild(a)
                a.click()
                document.body.removeChild(a)
                uni.showToast({ title: '已保存', icon: 'success' })
                // #endif

                // #ifndef H5
                // 移动端下载处理
                uni.saveImageToPhotosAlbum({
                    filePath: res.tempFilePath,
                    success() {
                        uni.showToast({ title: '已保存', icon: 'success' })
                    },
                    fail(err) {
                        console.error('保存图片失败:', err)
                        // 如果是没有权限，提示用户授权
                        if (err.errMsg === 'saveImageToPhotosAlbum:fail auth deny' || err.errMsg === 'saveImageToPhotosAlbum:fail:auth denied') {
                            uni.showModal({
                                title: '提示',
                                content: '需要您授权保存相册',
                                success: (modalRes) => {
                                    if (modalRes.confirm) {
                                        uni.openSetting({
                                            success(settingdata) {
                                                if (settingdata.authSetting['scope.writePhotosAlbum']) {
                                                    uni.showToast({ title: '获取权限成功，再次点击图片即可保存', icon: 'none' })
                                                } else {
                                                    uni.showToast({ title: '获取权限失败', icon: 'none' })
                                                }
                                            }
                                        })
                                    }
                                }
                            })
                        } else {
                            uni.showToast({ title: '保存失败', icon: 'error' })
                        }
                    }
                })
                // #endif
            },
            fail(err) {
                console.error('canvas转图片失败:', err)
                uni.showToast({ title: '生成图片失败', icon: 'error' })
            }
        })
    }, 200)
}

/** 清空二维码 */
function clear() {
    const ctx = uni.createCanvasContext(canvasId)
    if (!ctx) return
    // 清除画布区域
    ctx.clearRect(0, 0, props.width, props.height)
    // 绘制透明/白色背景
    ctx.setFillStyle(props.colorLight)
    ctx.fillRect(0, 0, props.width, props.height)
    ctx.draw()
    console.log('二维码已清空')
}

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

watch(() => props.text, (newVal) => {
    console.log('二维码文本变化:', newVal)
    if (!newVal) {
        clear()
    } else {
        drawQr()
    }
})

defineExpose({
    download,
    clear,
    drawQr
})
</script>

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

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

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