<script setup lang="ts">
/**
 * Props-driven QR code display.
 *
 * Generates a QR code into a `<canvas>` via the `qrcode` library,
 * lazy-imported on mount.
 *
 * When the host environment can't paint to a canvas (jsdom, SSR, or
 * hardened browsers), `renderQr` short-circuits — keeping consumer
 * tests in jsdom-based environments quiet and crash-free.
 */
import { computed, onMounted, ref, useTemplateRef, watch } from "vue"

// True only in real browsers — skipping the canvas detection call avoids
// jsdom's "Not implemented: getContext()" warning. See ChartDisplay.vue
// for the longer rationale.
const CANVAS_SUPPORTED: boolean =
  typeof document !== "undefined" &&
  !(typeof navigator !== "undefined" && /jsdom/i.test(navigator.userAgent))

export interface QrCodeDisplayProps {
  value?: string | number | null
  classList?: string[] | string
}

const props = defineProps<QrCodeDisplayProps>()

const content = computed<string>(() => {
  if (props.value === undefined || props.value === null) {
    return ""
  }
  return String(props.value)
})

const rootClass = computed<string>(() => {
  const cl = props.classList
  if (!cl) {
    return ""
  }
  return Array.isArray(cl) ? cl.join(" ") : cl
})

const canvasRef = useTemplateRef<HTMLCanvasElement>("canvasRef")
const error = ref<string>("")

async function renderQr(): Promise<void> {
  if (!CANVAS_SUPPORTED || !canvasRef.value || !content.value) {
    return
  }
  try {
    const mod = await import("qrcode")
    const QRCode = (mod as unknown as { default: { toCanvas: (canvas: HTMLCanvasElement, text: string, opts?: Record<string, unknown>) => Promise<void> } }).default
    await QRCode.toCanvas(canvasRef.value, content.value, {
      margin: 1,
      width: 160,
    })
    error.value = ""
  } catch (e) {
    error.value = e instanceof Error ? e.message : "Failed to render QR code"
  }
}

onMounted(() => {
  void renderQr()
})

watch(content, () => {
  void renderQr()
})
</script>

<template>
  <div
    class="inline-block"
    :class="rootClass"
    data-testid="qrcode-display"
  >
    <canvas
      ref="canvasRef"
      :aria-label="`QR code: ${content}`"
      role="img"
    />
    <p
      v-if="error"
      class="mt-1 text-xs text-destructive"
      data-testid="qrcode-error"
    >
      {{ error }}
    </p>
  </div>
</template>
