<script setup lang="ts">
/**
 * Props-driven single-select chip list. Each option becomes a clickable
 * Badge. When `clearable` is true, re-clicking the active chip clears
 * the selection.
 *
 *   <ListOption v-model="status" :options="[...]" label="Status" />
 */
import { computed } from "vue"
import type { SelectOptionLike } from "@/definitions/shared/select-options"
import { Badge } from "@/components/ui/badge"
import { FieldFrame } from "@/components/ui/field-frame"

export interface ListOptionProps {
  modelValue?: string | number | null
  options?: SelectOptionLike[]
  id?: string
  name?: string
  label?: string
  hideLabel?: boolean
  required?: boolean
  readonly?: boolean
  disabled?: boolean
  helpText?: string
  errors?: string[]
  clearable?: boolean
}

const props = withDefaults(defineProps<ListOptionProps>(), {
  errors: () => [],
  options: () => [],
})

const model = defineModel<string | number | null>("modelValue")

interface NormalisedOption {
  label: string
  value: string
  disabled: boolean
}

function normaliseOption(opt: SelectOptionLike): NormalisedOption {
  if (typeof opt === "string") {
    return { label: opt, value: opt, disabled: false }
  }
  return {
    label: opt.label,
    value: String(opt.value),
    disabled: Boolean(opt.disabled),
  }
}

const normalised = computed<NormalisedOption[]>(() =>
  (props.options ?? []).map(normaliseOption),
)

const currentValue = computed<string | undefined>(() => {
  if (model.value === undefined || model.value === null) {
    return undefined
  }
  return String(model.value)
})

function isActive(val: string): boolean {
  return currentValue.value === val
}

function selectValue(opt: NormalisedOption): void {
  if (opt.disabled || props.disabled || props.readonly) {
    return
  }
  if (currentValue.value === opt.value && props.clearable) {
    model.value = null
    return
  }
  model.value = opt.value
}
</script>

<template>
  <FieldFrame
    :label="label"
    :required="required"
    :hide-label="hideLabel"
    :help-text="helpText"
    :errors="errors"
  >
    <div
      class="flex flex-wrap gap-2"
      :data-element-name="name ?? undefined"
    >
      <Badge
        v-for="opt in normalised"
        :key="opt.value"
        as="button"
        type="button"
        :variant="isActive(opt.value) ? 'default' : 'outline'"
        size="lg"
        :class="[
          'cursor-pointer transition-colors',
          opt.disabled || disabled || readonly
            ? 'pointer-events-none opacity-50'
            : '',
        ]"
        :data-active="isActive(opt.value)"
        :aria-pressed="isActive(opt.value)"
        @click="selectValue(opt)"
      >
        {{ opt.label }}
      </Badge>
    </div>
  </FieldFrame>
</template>
