<script setup lang="ts">
/**
 * Props-driven time picker composition. Two numeric inputs (hours /
 * minutes) with a leading clock icon. Round-trips an `HH:mm` string.
 * `minuteStep` is applied to the minute input's `step` attribute.
 *
 *   <TimePicker v-model="opensAt" label="Opens at" />
 */
import { computed, ref, watchEffect } from "vue"
import { Clock } from "@lucide/vue"
import { Input } from "@/components/ui/input"
import { FieldFrame } from "@/components/ui/field-frame"

export interface TimePickerProps {
  modelValue?: string | null
  id?: string
  name?: string
  label?: string
  hideLabel?: boolean
  required?: boolean
  readonly?: boolean
  disabled?: boolean
  helpText?: string
  errors?: string[]
  minuteStep?: number
}

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

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

const hour = ref<string>("")
const minute = ref<string>("")

watchEffect(() => {
  const value = model.value
  if (!value) {
    hour.value = ""
    minute.value = ""
    return
  }
  const [hh, mm] = value.split(":")
  hour.value = hh ?? ""
  minute.value = (mm ?? "").slice(0, 2)
})

function pad(value: string): string {
  const n = Math.max(0, parseInt(value, 10) || 0)
  return n.toString().padStart(2, "0")
}

function emitCombined(): void {
  if (hour.value === "" && minute.value === "") {
    model.value = ""
    return
  }
  model.value = `${pad(hour.value || "0")}:${pad(minute.value || "0")}`
}

function onHourInput(value: string | number | undefined): void {
  const next = String(value ?? "")
  const numeric = Math.min(23, Math.max(0, parseInt(next, 10) || 0))
  hour.value = numeric.toString()
  emitCombined()
}

function onMinuteInput(value: string | number | undefined): void {
  const next = String(value ?? "")
  const numeric = Math.min(59, Math.max(0, parseInt(next, 10) || 0))
  minute.value = numeric.toString()
  emitCombined()
}

const step = computed<number>(() => {
  const raw = props.minuteStep
  return typeof raw === "number" && raw > 0 ? raw : 1
})
</script>

<template>
  <FieldFrame
    :label="label"
    :required="required"
    :hide-label="hideLabel"
    :for="id"
    :help-text="helpText"
    :errors="errors"
  >
    <div
      class="flex items-center gap-2"
      :data-element-name="name ?? undefined"
    >
      <Clock class="size-4 text-muted-foreground" />
      <Input
        type="number"
        min="0"
        max="23"
        step="1"
        :model-value="hour"
        class="w-20"
        :disabled="disabled"
        :readonly="readonly"
        :required="required"
        placeholder="HH"
        data-testid="time-hour"
        @update:model-value="onHourInput"
      />
      <span class="text-muted-foreground">:</span>
      <Input
        type="number"
        min="0"
        max="59"
        :step="step"
        :model-value="minute"
        class="w-20"
        :disabled="disabled"
        :readonly="readonly"
        :required="required"
        placeholder="MM"
        data-testid="time-minute"
        @update:model-value="onMinuteInput"
      />
    </div>
  </FieldFrame>
</template>
