<template>
  <span v-if="!hits.length" class="vm-dict-tag is-empty">—</span>
  <span v-else class="vm-dict-tag-list">
    <span
      v-for="(item, i) in hits"
      :key="`${String(item.value)}-${i}`"
      class="vm-dict-tag"
      :style="item.style"
    >
      {{ item.label }}
    </span>
  </span>
</template>

<script setup lang="ts">
import { computed } from 'vue'
import { getCrudStyle } from '../style'

defineOptions({ name: 'vm-dict-tag' })

type DictOpt = {
  label: string
  value: string | number | boolean
  type?: string
  color?: string
}

const props = defineProps<{
  /** 单值或字典 value 数组（多选列） */
  modelValue?:
    | string
    | number
    | boolean
    | null
    | Array<string | number | boolean | null | undefined>
  options?: DictOpt[]
}>()

function valuesOf(
  raw: unknown,
): Array<string | number | boolean> {
  if (raw == null || raw === '') return []
  if (Array.isArray(raw)) {
    return raw.filter(
      (v): v is string | number | boolean =>
        v != null && v !== '',
    )
  }
  return [raw as string | number | boolean]
}

function matchOpt(
  options: DictOpt[] | undefined,
  v: string | number | boolean,
): DictOpt | undefined {
  return options?.find(
    (d) => d.value === v || String(d.value) === String(v),
  )
}

function styleOf(opt: DictOpt, idx: number) {
  if (opt.color) {
    return { background: `${opt.color}22`, color: opt.color }
  }
  const colors = getCrudStyle().colors
  const c = colors[idx % colors.length] || 'var(--brand)'
  return { background: `${c}22`, color: c }
}

const hits = computed(() => {
  const opts = props.options || []
  const out: Array<{
    label: string
    value: string | number | boolean
    style: Record<string, string>
  }> = []
  for (const v of valuesOf(props.modelValue)) {
    const hit = matchOpt(opts, v)
    if (!hit) continue
    const idx = opts.findIndex((d) => d === hit)
    out.push({
      label: hit.label,
      value: hit.value,
      style: styleOf(hit, idx < 0 ? 0 : idx),
    })
  }
  return out
})
</script>

<style lang="scss" scoped>
.vm-dict-tag-list {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px;
  max-width: 100%;
}

.vm-dict-tag {
  display: inline-flex;
  padding: 2px 8px;
  border-radius: 8px;
  font-size: 12px;
  font-weight: 600;

  &.is-empty {
    color: var(--muted-foreground);
    background: transparent;
  }
}
</style>
