<script setup lang="ts">
/**
 * Props-driven banner display.
 *
 * Wraps the Alert primitive: `title` is the alert title and `value`
 * is the description. `variant` selects the colour scheme and `icon`
 * is a lucide icon name (PascalCase or kebab-case). The library is
 * lazy-imported so we only pay for it when an icon is requested.
 */
import { computed, ref, watch, type Component } from "vue"
import { Info } from "@lucide/vue"
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"
import type { AlertVariants } from "@/components/ui/alert"

export interface BannerDisplayProps {
  value?: string | number | null
  title?: string
  variant?: AlertVariants["variant"]
  icon?: string
  classList?: string[] | string
}

const props = withDefaults(defineProps<BannerDisplayProps>(), {
  variant: "default",
})

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
})

function toPascalCase(input: string): string {
  return input
    .replace(/[-_\s]+(.)?/g, (_, ch?: string) => (ch ? ch.toUpperCase() : ""))
    .replace(/^(.)/, (m) => m.toUpperCase())
}

const ResolvedIcon = ref<Component | null>(null)

async function loadIcon(name: string | undefined): Promise<void> {
  if (!name) {
    ResolvedIcon.value = null
    return
  }
  const mod = await import("@lucide/vue")
  const registry = mod as unknown as Record<string, Component | undefined>
  ResolvedIcon.value = registry[toPascalCase(name)] ?? null
}

watch(
  () => props.icon,
  (next) => {
    void loadIcon(next)
  },
  { immediate: true },
)
</script>

<template>
  <Alert
    :variant="variant"
    :class="rootClass"
    data-testid="banner-display"
  >
    <component
      :is="ResolvedIcon"
      v-if="icon && ResolvedIcon"
    />
    <Info v-else-if="!icon" />
    <AlertTitle v-if="title">
      {{ title }}
    </AlertTitle>
    <AlertDescription v-if="content">
      {{ content }}
    </AlertDescription>
  </Alert>
</template>
