<script setup>
// Wraps PrimeVue InputText; optional label/description above. Extra attrs (e.g. aria-label) via $attrs.
import { computed, ref } from "vue";
import InputText from "primevue/inputtext";

const props = defineProps({
  label: { type: String, default: "" }, // optional; shown above input
  description: { type: String, default: "" }, // optional hint below label
  modelValue: { type: [String, Number], default: "" }, // v-model
  type: { type: String, default: "text" }, // text | email | tel | password | number
  placeholder: { type: String, default: "" },
  disabled: { type: Boolean, default: false },
  readonly: { type: Boolean, default: false },
  invalid: { type: Boolean, default: false }, // error state (also derived from error when set)
  error: { type: String, default: "" }, // optional error message shown below input (e.g. validation)
  required: { type: Boolean, default: false }, // show red asterisk in label and set native required on input
  variant: {
    type: String,
    default: undefined,
    validator: (v) => !v || ["outlined", "filled"].includes(v),
  }, // outlined | filled
  fluid: { type: Boolean, default: false }, // full width
  id: { type: String, default: undefined }, // for label for; auto-generated if omitted (stable per instance)
  class: { type: [String, Object, Array], default: "w-full" }, // default full width for form layout
});

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

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

const handleInput = (event) => {
  emit("update:modelValue", event.target.value);
  emit("input", event);
};

const handleChange = (event) => {
  emit("change", event);
};
</script>

<template>
  <div class="flex flex-col" :class="props['class']">
    <div v-if="label || description" class="mb-1 flex flex-col">
      <label
        v-if="label"
        :for="inputId"
        class="block text-md font-medium leading-6 text-surface-950 dark:text-surface-0"
      >
        {{ label
        }}<span v-if="required" class="text-red-500" aria-hidden="true">
          *</span
        >
      </label>
      <div
        v-if="description"
        class="mb-1 text-base font-normal leading-normal text-surface-500 dark:text-surface-400"
      >
        {{ description }}
      </div>
    </div>
    <InputText
      :id="inputId"
      :model-value="modelValue"
      :type="type"
      :placeholder="placeholder"
      :disabled="disabled"
      :readonly="readonly"
      :invalid="invalidState"
      :required="required"
      :variant="variant"
      :fluid="fluid"
      :aria-invalid="invalidState"
      :aria-describedby="error ? errorId : undefined"
      v-bind="$attrs"
      @update:model-value="emit('update:modelValue', $event)"
      @blur="emit('blur', $event)"
      @focus="emit('focus', $event)"
      @input="handleInput"
      @keydown="emit('keydown', $event)"
      @keyup="emit('keyup', $event)"
      @change="handleChange"
    />
    <small
      v-if="error"
      :id="errorId"
      class="block text-red-500 mt-1 text-sm"
      role="alert"
      >{{ error }}</small
    >
  </div>
</template>
