<script setup>
// Wraps PrimeVue MultiSelect; optional label/required/error like BaseSelect. Slots (value, chip, etc.) forwarded to MultiSelect.
import { computed, ref } from "vue";
import MultiSelect from "primevue/multiselect";

const props = defineProps({
  label: { type: String, default: "" },
  modelValue: { type: Array, default: () => [] },
  options: { type: Array, default: () => [] },
  optionLabel: { type: [String, Function], default: undefined },
  optionValue: { type: [String, Function], default: undefined },
  placeholder: { type: String, default: "" },
  disabled: { type: Boolean, default: false },
  invalid: { type: Boolean, default: false },
  error: { type: String, default: "" },
  required: { type: Boolean, default: false },
  filter: { type: Boolean, default: false },
  filterPlaceholder: { type: String, default: undefined },
  display: {
    type: String,
    default: "chip",
    validator: (v) => ["comma", "chip"].includes(v),
  },
  maxSelectedLabels: {
    type: Number,
    default: 2,
  } /** Max number of selected items to display */,
  selectedItemsLabel: {
    type: String,
    default: "{0} geselecteerd",
  } /** Label template when more than maxSelectedLabels are selected (PrimeVue placeholder {0} = count). */,
  fluid: { type: Boolean, default: true },
  id: { type: String, default: undefined },
  class: { type: [String, Object, Array], default: "w-full" },
});

const emit = defineEmits([
  "update:modelValue",
  "change",
  "focus",
  "blur",
  "filter",
]);

const fallbackId = ref(
  `base-multiselect-${Math.random().toString(36).slice(2, 11)}`,
);
const selectId = computed(() => props.id ?? fallbackId.value);
const invalidState = computed(() => props.invalid || !!props.error);
const errorId = computed(() => `${selectId.value}-error`);
</script>

<template>
  <div class="flex flex-col" :class="props['class']">
    <div v-if="label" class="flex flex-col mb-2">
      <label
        :for="selectId"
        class="block text-surface-950 dark:text-surface-0 text-md font-medium leading-7"
      >
        {{ label
        }}<span v-if="required" class="text-red-500" aria-hidden="true">
          *</span
        >
      </label>
    </div>
    <MultiSelect
      :input-id="selectId"
      :model-value="modelValue"
      :options="options"
      :option-label="optionLabel"
      :option-value="optionValue"
      :placeholder="placeholder"
      :disabled="disabled"
      :invalid="invalidState"
      :aria-invalid="invalidState"
      :aria-describedby="error ? errorId : undefined"
      :filter="filter"
      :filter-placeholder="filterPlaceholder"
      :display="display"
      :fluid="fluid"
      :max-selected-labels="maxSelectedLabels"
      :selected-items-label="selectedItemsLabel"
      v-bind="$attrs"
      @update:model-value="emit('update:modelValue', $event)"
      @change="emit('change', $event)"
      @focus="emit('focus', $event)"
      @blur="emit('blur', $event)"
      @filter="emit('filter', $event)"
    >
      <template v-if="$slots.value" #value="slotProps">
        <slot name="value" v-bind="slotProps" />
      </template>
      <template v-if="$slots.chip" #chip="slotProps">
        <slot name="chip" v-bind="slotProps" />
      </template>
      <template v-if="$slots.item" #item="slotProps">
        <slot name="item" v-bind="slotProps" />
      </template>
      <template v-if="$slots.header" #header="slotProps">
        <slot name="header" v-bind="slotProps" />
      </template>
      <template v-if="$slots.empty" #empty>
        <slot name="empty" />
      </template>
      <template v-if="$slots.emptyfilter" #emptyfilter>
        <slot name="emptyfilter" />
      </template>
    </MultiSelect>
    <small v-if="error" :id="errorId" class="text-red-500 mt-1" role="alert">{{
      error
    }}</small>
  </div>
</template>
