<script setup>
// A date the owner may only half know.
//
// A car's build date is often "2015", or "March 2015", and no more: the VIN
// plate carries a month, the registration papers a day, a grey import neither.
// A field that insists on all three makes the owner either invent a day or
// leave the whole thing blank, and both lose what they actually knew.
//
// The value is an ISO 8601 reduced-precision date — "2015", "2015-03" or
// "2015-03-10" — which is what the API stores and what formatPartialDate
// prints back at exactly the precision it was given.
import { ref, watch } from "vue";
import { t } from "../i18n";
import DateField from "./DateField.vue";

const props = defineProps({ modelValue: { type: String, default: "" } });
const emit = defineEmits(["update:modelValue"]);

const LENGTH = { year: 4, month: 7, day: 10 };

// How much of a date a value carries. An empty field reads as a full date,
// which is what this field was before and what most people will still enter.
function precisionOf(value) {
  const v = value || "";
  if (v.length >= LENGTH.day) return "day";
  if (v.length >= LENGTH.month) return "month";
  if (v.length >= LENGTH.year) return "year";
  return "day";
}

// Kept beside the value rather than derived from it: an empty field has no
// precision to read, and choosing "Year only" before typing anything would
// otherwise snap straight back to a full date. A value arriving from outside
// (the form loading a car) does set it, since then there is something to read.
const precision = ref(precisionOf(props.modelValue));
const year = ref(precisionOf(props.modelValue) === "year" ? props.modelValue : "");
watch(
  () => props.modelValue,
  (value) => {
    if (!value) return;
    precision.value = precisionOf(value);
    if (precision.value === "year") year.value = value;
  }
);

// Narrowing keeps what is still true: the day dropped from "2015-03-10" leaves
// "2015-03", which is the point of the control. Widening clears, because there
// is nothing to widen it with — and leaving "2015" behind an empty month box
// would store a date the field on screen isn't showing.
function setPrecision(next) {
  const kept = LENGTH[next] < LENGTH[precision.value] ? (props.modelValue || "").slice(0, LENGTH[next]) : "";
  precision.value = next;
  year.value = next === "year" ? kept : "";
  emit("update:modelValue", kept);
}

// A year is typed, not picked — a date picker asking you to walk back to 1998 is
// worse than four keystrokes. Digits only, and nothing is emitted until all four
// are there, so a half-typed "20" is never saved as a year.
watch(year, (value) => {
  const digits = String(value).replace(/\D/g, "").slice(0, 4);
  if (digits !== value) {
    year.value = digits; // re-enters here with the cleaned value
    return;
  }
  emit("update:modelValue", digits.length === LENGTH.year ? digits : "");
});
</script>

<template>
  <div class="space-y-1.5">
    <select :value="precision" class="dh-input" @change="setPrecision($event.target.value)">
      <option value="day">{{ t("forms.car.precision.day") }}</option>
      <option value="month">{{ t("forms.car.precision.month") }}</option>
      <option value="year">{{ t("forms.car.precision.year") }}</option>
    </select>

    <!-- One control per precision: a date, a month, and a plain box for the
         year. The first two are DateField, so a build date is typed in the same
         order as every other date in the app. -->
    <DateField
      v-if="precision === 'day'"
      :model-value="modelValue"
      @update:model-value="emit('update:modelValue', $event)"
    />
    <DateField
      v-else-if="precision === 'month'"
      precision="month"
      :model-value="modelValue"
      @update:model-value="emit('update:modelValue', $event)"
    />
    <input
      v-else
      v-model="year"
      type="text"
      inputmode="numeric"
      maxlength="4"
      placeholder="2015"
      class="dh-input data"
    />
  </div>
</template>
