<template>
  <v-text-field
    v-model="localValue"
    :type="inputHtmlType"
    :inputmode="inputMode"
    :label="opcoes?.rotulo"
    :placeholder="opcoes?.placeholder"
    :counter="opcoes?.limiteCaracteres"
    :maxlength="opcoes?.limiteCaracteres"
    v-bind="attrs"
    @focus="() => emit('focus')"
    @blur="() => emit('blur')"
    @input="onInput"
  />
</template>

<script lang="ts">
import { computed, defineComponent, PropType } from "vue";
import type { PadroesEntradas } from "./tiposEntradas";
import { formatarCpfCnpj } from "./utils/cpfCnpj";
import { formatTelefone } from "./utils/telefone";
import { formatarCep } from "./utils/cep";

type EntradaTexto = PadroesEntradas["texto"];

export default defineComponent({
  name: "EliEntradaTexto",
  inheritAttrs: false,
  props: {
    /** Interface padrão (EliEntrada): value + opcoes. */
    value: {
      type: [String, null] as unknown as PropType<EntradaTexto["value"]>,
      default: undefined,
    },
    opcoes: {
      type: Object as PropType<EntradaTexto["opcoes"]>,
      required: true,
    },
  },
  emits: {
    "update:value": (_v: EntradaTexto["value"]) => true,
    /** Compat Vue2 (v-model padrão: value + input) */
    input: (_v: EntradaTexto["value"]) => true,
    change: (_v: EntradaTexto["value"]) => true,
    focus: () => true,
    blur: () => true,
  },
  setup(props, { attrs, emit }) {
    const formato = computed(() => props.opcoes?.formato ?? "texto");

    const localValue = computed<EntradaTexto["value"]>({
      get: () => props.value,
      set: (v) => {
        emit("update:value", v);
        emit("input", v);
        emit("change", v);
      },
    });

    const inputHtmlType = computed(() => {
      if (formato.value === "email") return "email";
      if (formato.value === "url") return "url";
      return "text";
    });

    const inputMode = computed<string | undefined>(() => {
      if (formato.value === "telefone") return "tel";
      if (formato.value === "cpfCnpj" || formato.value === "cep") return "numeric";
      return undefined;
    });

    function aplicarFormato(valor: string) {
      switch (formato.value) {
        case "telefone":
          return formatTelefone(valor);
        case "cpfCnpj":
          return formatarCpfCnpj(valor);
        case "cep":
          return formatarCep(valor);
        default:
          return valor;
      }
    }

    function onInput(e: Event) {
      const target = e.target as HTMLInputElement;
      const resultado = aplicarFormato(target.value);

      // garante que o input mostre o valor formatado
      target.value = resultado;

      // regra do projeto: value sempre igual ao que aparece
      localValue.value = resultado;
    }

    return { attrs, emit, localValue, inputHtmlType, inputMode, onInput };
  },
});
</script>

<style scoped></style>
