<script setup lang="ts">
/**
 * Props-driven typography display.
 *
 * The `contentType` sub-style selects the semantic tag and Tailwind
 * classes (heading-1 .. heading-6, paragraph, lead, small, caption,
 * code, quote).
 *
 *   <TypeDisplay value="Hello, world" content-type="heading-1" />
 */
import { computed, h, type Component } from "vue"
import type { DisplayContentType } from "@/definitions/elements/DisplayElement"

export interface TypeDisplayProps {
  value?: string | number | null
  contentType?: DisplayContentType
  classList?: string[] | string
}

const props = withDefaults(defineProps<TypeDisplayProps>(), {
  contentType: "paragraph",
})

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

interface VariantSpec {
  tag: string
  classes: string
}

const VARIANTS: Record<DisplayContentType, VariantSpec> = {
  "heading-1": { tag: "h1", classes: "text-4xl font-bold tracking-tight" },
  "heading-2": { tag: "h2", classes: "text-3xl font-semibold tracking-tight" },
  "heading-3": { tag: "h3", classes: "text-2xl font-semibold" },
  "heading-4": { tag: "h4", classes: "text-xl font-semibold" },
  "heading-5": { tag: "h5", classes: "text-lg font-semibold" },
  "heading-6": { tag: "h6", classes: "text-base font-semibold" },
  paragraph: { tag: "p", classes: "leading-7" },
  lead: { tag: "p", classes: "text-lg text-muted-foreground" },
  small: { tag: "small", classes: "text-xs" },
  caption: { tag: "span", classes: "text-xs text-muted-foreground" },
  code: { tag: "code", classes: "font-mono bg-muted px-1 rounded text-sm" },
  quote: { tag: "blockquote", classes: "border-l-4 pl-4 italic text-muted-foreground" },
}

const variant = computed<VariantSpec>(() => {
  return VARIANTS[props.contentType] ?? VARIANTS.paragraph
})

const Rendered: Component = {
  render() {
    return h(
      variant.value.tag,
      {
        class: [variant.value.classes, rootClass.value].filter(Boolean).join(" "),
        "data-testid": "type-display",
        "data-content-type": props.contentType,
      },
      content.value,
    )
  },
}
</script>

<template>
  <Rendered />
</template>
