<template>
  <div class="eli-data-hora">
    <!--
      Implementação propositalmente “simples” e estável:
      - Usa o input nativo `datetime-local` dentro do v-text-field.
      - Evita depender de componentes experimentais (labs) do Vuetify.
      - Mantém v-model como string ISO local: `YYYY-MM-DDTHH:mm`.

      Observação importante:
      - `datetime-local` NÃO armazena timezone.
      - Se o projeto precisar persistir em UTC, converta no consumidor.
    -->
    <v-text-field
      v-model="valor"
      :type="tipoInput"
      :label="rotulo"
      :placeholder="placeholder"
      :disabled="desabilitado"
      :clearable="limpavel"
      :error="erro"
      :error-messages="mensagensErro"
      :hint="dica"
      :persistent-hint="dicaPersistente"
      :density="densidade"
      :variant="variante"
      :min="minLocal"
      :max="maxLocal"
      v-bind="attrs"
      @focus="emit('foco')"
      @blur="emit('desfoco')"
    />
  </div>
</template>

<script lang="ts">
import { computed, defineComponent, PropType } from "vue";
import dayjs from "dayjs";
import type { CampoDensidade, CampoVariante } from "../../tipos";

/**
 * EliDataHora
 *
 * Campo para entrada de data + hora.
 *
 * Modelo:
 * - O componente **recebe** `modelValue` em ISO 8601 (UTC `Z` ou com offset).
 * - Converte para horário local para exibir no `datetime-local`.
 * - Ao editar, **emite** ISO 8601 com o **offset local**.
 */
export default defineComponent({
  name: "EliDataHora",
  inheritAttrs: false,

  props: {
    /**
     * Valor em ISO 8601:
     * - com offset (ex.: `2026-01-09T13:15:00-03:00`)
     * - ou UTC absoluto (ex.: `2026-01-09T16:15:00Z`)
     */
    modelValue: {
      type: String as PropType<string | null>,
      default: null,
    },

    /**
     * Define o tipo de entrada.
     * - `dataHora`: usa `datetime-local`
     * - `data`: usa `date`
     */
    modo: {
      type: String as PropType<"data" | "dataHora">,
      default: "dataHora",
    },

    /** Rótulo exibido no v-text-field (Vuetify). */
    rotulo: {
      type: String,
      default: "Data e hora",
    },

    /** Placeholder do input. */
    placeholder: {
      type: String,
      default: "",
    },

    /** Desabilita a interação. */
    desabilitado: {
      type: Boolean,
      default: false,
    },

    /** Se true, mostra ícone para limpar o valor (Vuetify clearable). */
    limpavel: {
      type: Boolean,
      default: false,
    },

    /** Estado de erro (visual). */
    erro: {
      type: Boolean,
      default: false,
    },

    /** Mensagens de erro. */
    mensagensErro: {
      type: [String, Array] as PropType<string | string[]>,
      default: () => [],
    },

    /** Texto de apoio. */
    dica: {
      type: String,
      default: "",
    },

    /** Mantém a dica sempre visível. */
    dicaPersistente: {
      type: Boolean,
      default: false,
    },

    /** Densidade do campo (Vuetify). */
    densidade: {
      type: String as PropType<CampoDensidade>,
      default: "comfortable",
    },

    /** Variante do v-text-field (Vuetify). */
    variante: {
      type: String as PropType<CampoVariante>,
      default: "outlined",
    },

    /**
     * Valor mínimo permitido.
     * ISO 8601 (offset ou `Z`).
     */
    min: {
      // ISO 8601 (offset ou Z)
      type: String as PropType<string | undefined>,
      default: undefined,
    },

    /**
     * Valor máximo permitido.
     * ISO 8601 (offset ou `Z`).
     */
    max: {
      // ISO 8601 (offset ou Z)
      type: String as PropType<string | undefined>,
      default: undefined,
    },
  },

  emits: {
    /** v-model padrão. */
    "update:modelValue": (_valor: string | null) => true,
    /** Alias para consumidores que querem um evento semântico. */
    alterar: (_valor: string | null) => true,
    foco: () => true,
    desfoco: () => true,
  },

  setup(props, { emit, attrs }) {
    const tipoInput = computed<"date" | "datetime-local">(() =>
      props.modo === "data" ? "date" : "datetime-local"
    );

    // Converte ISO (Z/offset) para o formato que o `datetime-local` aceita.
    function isoParaInputDatetime(valorIso: string): string {
      // `dayjs(valorIso)` interpreta ISO com timezone e converte para o local do usuário.
      if (props.modo === "data") {
        return dayjs(valorIso).format("YYYY-MM-DD");
      }

      return dayjs(valorIso).format("YYYY-MM-DDTHH:mm");
    }

    // Converte o valor do input (`YYYY-MM-DDTHH:mm`) para ISO 8601 com offset local.
    function inputDatetimeParaIsoLocal(valorInput: string): string {
      // `format()` retorna ISO 8601 com offset local.
      // Em modo `data`, normalizamos para o começo do dia (00:00:00) no fuso local.
      if (props.modo === "data") {
        return dayjs(`${valorInput}T00:00`).format();
      }

      return dayjs(valorInput).format();
    }

    const valor = computed<string>({
      get: () => {
        if (!props.modelValue) return "";
        return isoParaInputDatetime(props.modelValue);
      },
      set: (v) => {
        // O `datetime-local` entrega string ou "" quando limpo.
        const normalizado = v && v.length > 0 ? v : null;
        if (!normalizado) {
          emit("update:modelValue", null);
          emit("alterar", null);
          return;
        }

        const valorEmitido = inputDatetimeParaIsoLocal(normalizado);
        emit("update:modelValue", valorEmitido);
        emit("alterar", valorEmitido);
      },
    });

    const minLocal = computed<string | undefined>(() => {
      if (!props.min) return undefined;
      return isoParaInputDatetime(props.min);
    });

    const maxLocal = computed<string | undefined>(() => {
      if (!props.max) return undefined;
      return isoParaInputDatetime(props.max);
    });

    return { attrs, valor, emit, minLocal, maxLocal, tipoInput };
  },
});
</script>

<style scoped>
.eli-data-hora {
  width: 100%;
}
</style>

