<script setup>
// Wraps PrimeVue DatePicker.
// - selectionMode `single` (default): v-model is `YYYY-MM-DD` or `""` (API / Laravel date fields).
// - selectionMode `range`: v-model is what PrimeVue emits (`Date[]` | `Date` | `null`) — for table filters.
// Other DatePicker options pass through $attrs; defaults: showIcon, fluid, showClear, appendTo body.
import { computed, ref, useAttrs } from "vue";
import DatePicker from "primevue/datepicker";

defineOptions({ inheritAttrs: false });

const props = defineProps({
  label: { type: String, default: "" },
  description: { type: String, default: "" },
  /** `single`: string YYYY-MM-DD or "". `range`: Date / Date[] / null from PrimeVue. */
  modelValue: { type: [String, Date, Array], default: "" },
  selectionMode: {
    type: String,
    default: "single",
    validator: (v) => v === "single" || v === "range",
  },
  error: { type: String, default: "" },
  required: { type: Boolean, default: false },
  id: { type: String, default: undefined },
  class: { type: [String, Object, Array], default: "w-full" },
});

const attrs = useAttrs();
const emit = defineEmits(["update:modelValue"]);

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

function parseYmd(s) {
  if (s == null || typeof s !== "string") return null;
  const t = s.trim();
  if (!t) return null;
  const m = t.match(/^(\d{4})-(\d{2})-(\d{2})$/);
  if (!m) return null;
  const d = new Date(Number(m[1]), Number(m[2]) - 1, Number(m[3]), 12, 0, 0, 0);
  return Number.isNaN(d.getTime()) ? null : d;
}

function toYmd(d) {
  if (!(d instanceof Date) || Number.isNaN(d.getTime())) return "";
  const y = d.getFullYear();
  const mo = String(d.getMonth() + 1).padStart(2, "0");
  const day = String(d.getDate()).padStart(2, "0");
  return `${y}-${mo}-${day}`;
}

const pickerValue = computed(() => {
  if (props.selectionMode === "range") {
    const v = props.modelValue;
    if (v == null || v === "") return null;
    if (Array.isArray(v)) return v;
    if (v instanceof Date) return v;
    return null;
  }
  const s = typeof props.modelValue === "string" ? props.modelValue : "";
  return parseYmd(s);
});

function onPickerUpdate(val) {
  if (props.selectionMode === "range") {
    emit("update:modelValue", val);
    return;
  }
  if (val == null) {
    emit("update:modelValue", "");
    return;
  }
  emit("update:modelValue", toYmd(val));
}

const pickerAttrs = computed(() => {
  const rest = { ...attrs };
  delete rest.class;
  delete rest.style;
  delete rest.invalid;
  delete rest["onUpdate:modelValue"];
  return {
    showIcon: true,
    fluid: true,
    showClear: true,
    appendTo: "body",
    dateFormat: "dd/mm/yy",
    selectionMode: props.selectionMode,
    ...rest,
  };
});
</script>

<template>
  <div class="flex flex-col" :class="props['class']">
    <div v-if="label || description" class="flex flex-col mb-2">
      <label
        v-if="label"
        :for="inputId"
        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
        v-if="description"
        class="text-surface-500 dark:text-surface-400 text-base font-normal leading-normal mt-1"
      >
        {{ description }}
      </div>
    </div>
    <DatePicker
      :input-id="inputId"
      v-bind="pickerAttrs"
      :model-value="pickerValue"
      :invalid="invalidState"
      :required="required"
      :aria-invalid="invalidState"
      :aria-describedby="error ? errorId : undefined"
      @update:model-value="onPickerUpdate"
    />
    <small
      v-if="error"
      :id="errorId"
      class="block text-red-500 mt-1 text-sm"
      role="alert"
      >{{ error }}</small
    >
  </div>
</template>
