<template>
  <div
    :class="[
      {'ui-input--filled': isFilled || isAutoFilled},
      {'ui-input--focused': isFocused},
      {'ui-input--disabled': disabled},
      {'ui-input--error': error},
      {'ui-input--textarea': isTextArea},
      {'ui-input--icon': isPassword || icon},
      {'ui-input--pre-icon': preIcon},
      `ui-input--${size}`,
    ]"
    class="ui-input"
  >
    <label
      v-if="label"
      :class="{'_visually-hidden': hideLabel}"
      :for="name"
      class="ui-input__label"
    >
      <UiIcon
        v-if="labelIcon"
        :name="labelIcon"
        size="16"
      />
      {{ label }}
    </label>
    <label
      v-else-if="placeholder"
      :for="name"
      class="_visually-hidden"
    >{{ placeholder }}</label>
    <div class="ui-input__wrapper">
      <UiIcon
        v-if="preIcon"
        :name="preIcon"
        :size="preIconSize"
        class="ui-input__pre-icon"
      />
      <textarea
        v-if="isTextArea"
        ref="inputRef"
        :id="name"
        :value="modelValue"
        :name="name"
        :enterkeyhint="enterkeyhint"
        :tabindex="disabled ? '-1' : '0'"
        class="ui-input__input"
        rows="3"
        spellcheck="false"
        v-bind="$attrs"
        @input="onInput"
        @focus="onFocus"
        @blur="onBlur"
        @keyup.enter="(event) => emit('enter', event)"
      />
      <input
        v-else
        ref="inputRef"
        :id="name"
        :name="name"
        :type="showText ? 'text' : type"
        :inputmode="inputmode"
        :enterkeyhint="enterkeyhint"
        :value="normalizedValue"
        :autocomplete="autocomplete"
        :autofocus="autofocus"
        :tabindex="disabled ? '-1' : '0'"
        :placeholder="placeholder"
        class="ui-input__input"
        autocapitalize="off"
        spellcheck="false"
        @input="onInput"
        @focus="onFocus"
        @blur="onBlur"
        @keyup.enter="(event) => emit('enter', event)"
      >
      <button
        v-if="isPassword || icon"
        type="button"
        class="ui-input__button"
        @click="onButtonInputClick"
      >
        <UiIcon
          :name="isPassword ? 'show' : icon || ''"
          class="ui-input__button-icon"
          size="20"
        />
      </button>
    </div>
    <!--    <p-->
    <!--        v-if="error"-->
    <!--        class="ui-input__error"-->
    <!--    >-->
    <!--      <UiIcon-->
    <!--          name="danger"-->
    <!--          size="16"-->
    <!--      />-->
    <!--      {{ error }}-->
    <!--    </p>-->
  </div>
</template>

<script setup lang="ts">
import type { InputTypes } from '../../types';

const props = withDefaults(defineProps<{
  modelValue: string | number | undefined
  type?: InputTypes
  inputmode?: 'text' | 'numeric' | 'email'
  enterkeyhint?: 'enter' | 'done' | 'go' | 'next' | 'previous' | 'search' | 'send'
  error?: boolean
  success?: string | boolean
  size?: 'm' | 's'
  autofocus?: boolean
  disabled?: boolean
  autocomplete?: string
  name?: string
  label?: string
  hideLabel?: boolean
  placeholder?: string
  icon?: string
  labelIcon?: string
  preIcon?: string
  preIconSize?: string
}>(), {
  type: 'text',
  inputmode: 'text',
  size: 'm'
});

const emit = defineEmits<{
  (eventName: 'update:modelValue', value: string): void
  (eventName: 'focus', event: FocusEvent): void
  (eventName: 'blur', event: FocusEvent): void
  (eventName: 'enter', event: KeyboardEvent): void
  (eventName: 'update:error', value: boolean): void
  (eventName: 'icon-click'): void
}>();

const showText = ref(false);

const inputRef = ref<HTMLInputElement | HTMLTextAreaElement>();

defineExpose({ focus: () => inputRef.value?.focus() });

const isTextArea = computed(() => props.type === 'textarea');

const isFilled = computed(() => {
  return props.modelValue && String(props.modelValue).length > 0;
});

const isFocused = ref(false);
const isAutoFilled = ref(false);
const isPassword = computed(() => props.type === 'password');

function onFocus(event: FocusEvent) {
  isFocused.value = true;
  isAutoFilled.value = false;
  emit('focus', event);
}

function onBlur(event: FocusEvent) {
  isFocused.value = false;
  emit('blur', event);
}

function onInput(event: Event) {
  emit('update:modelValue', event.target?.value);
  if (props.error) {
    emit('update:error', false);
  }
}

function onButtonInputClick() {
  if (props.type === 'password') {
    showText.value = !showText.value;
  }
  emit('icon-click');
}

const isDate = computed(() => props.type === 'date');

const normalizedValue = computed(() => {
  if (isDate.value && props.modelValue === '1970-01-01') {
    return '';
  }
  return props.modelValue;
});
</script>

<style lang="scss">
.ui-input {
  display: grid;
  width: 100%;
}

.ui-input__wrapper {
  --padding-block: 12px;
  --padding-inline: 16px;

  position: relative;
  width: 100%;
  background-color: var(--input-bg, #{$input-bg});
  color: var(--input-text, #{$input-text});
  border-radius: $radius + 4px;
  border: 1px solid var(--input-border, #{$input-border});
  transition: var(--transition) border-color;
  overflow: hidden;

  @include hover(opacity, border-color) {
    opacity: 0.9;
  }
}

.ui-input__label {
  @include font-sm;

  display: flex;
  flex-wrap: nowrap;
  column-gap: 8px;
  align-items: center;
  color: var(--input-label, #{$input-label});
  margin-bottom: 8px;
}

.ui-input__input {
  padding-block: 12px;
  padding-inline: 16px;
  background-color: transparent;
  width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--input-text, #{$input-text});
  transition: var(--transition) transform;
  resize: none;
  font: inherit;
  font-size: 16px;
  border: 1px solid transparent;

  &:focus {
    outline: none;
  }

  @include from-br(sm) {
    padding-block: 8px;
    padding-inline: 16px;
    font-size: 14px;
  }
}

.ui-input__input::placeholder {
  color: var(--input-placeholder, #{$input-placeholder});

  @include to-br(sm) {
    @include font-sm;
  }
}

.ui-input.ui-input--focused .ui-input__wrapper {
  border-color: var(--input-border--focus, #{$input-border--focus});
}

.ui-input.ui-input--disabled .ui-input__wrapper {
  background-color: var(--input-bg--disabled, transparent);
  outline: 1px solid var(--input-text--disabled, #{$input-text--disabled});
  user-select: none;
  pointer-events: none;
}

.ui-input.ui-input--disabled .ui-input__wrapper,
.ui-input.ui-input--disabled .ui-input__input {
  color: var(--input-text--disabled, #{$input-text--disabled});
}

.ui-input.ui-input--error .ui-input__wrapper {
  border-color: var(--input-border--error, #{$input-border--error});
}

.ui-input__button {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  right: var(--padding-inline);
  padding: 0;
  background-color: transparent;
  border: none;
  color: var(--input-button-text, #{$input-button-text});

  &::after {
    @include area-point;
  }

  @include from-br(sm) {
    cursor: pointer;
  }
}

.ui-input__button-icon {
  width: 20px;
  height: 20px;
  color: var(--input-icon, #{$input-icon});

  @media (hover: hover) {
    transition: var(--transition) color;
  }
}

.ui-input__button:is(:hover, :focus-visible) .ui-input__button-icon {
  @media (hover: hover) {
    color: var(--input-button-text--hover, #{$input-button-text--hover});
  }
}

.ui-input__label.ui-input__label--external {
  position: static;
  margin-bottom: 8px;
}

.ui-input__input[type="date"]::-webkit-calendar-picker-indicator {
  cursor: pointer;
  opacity: 0.6;
  filter: invert(0.8);
}

.ui-input__input[type="date"]::-webkit-calendar-picker-indicator:hover {
  opacity: 1
}

.ui-input__pre-icon {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  left: 12px;
  color: var(--input-pre-icon, #{$input-pre-icon});
}

.ui-input.ui-input--s {
  --input-text: var(--input-s-text, #{$input-s-text});
  --input-autofill-text: var(--input-s-text, #{$input-s-text});
}

.ui-input.ui-input--s .ui-input__input {
  padding: 8px 16px;
  background-color: var(--input-s-bg, #{$input-s-bg});
  border: 1px solid var(--input-s-border, #{$input-s-border});

  @include from-br(sm) {
    @include font-sm;
  }
}

.ui-input.ui-input--pre-icon .ui-input__input {
  padding-left: 36px;
}

.ui-input.ui-input--s .ui-input__wrapper {
  border-color: var(--input-s-border, #{$input-s-border});
  background-color: var(--input-s-bg, #{$input-s-bg});
}

.ui-input--s.ui-input--focused .ui-input__wrapper {
  border-color: var(--input-s-border--focus, #{$input-s-border--focus});
}

.ui-input.ui-input--icon .ui-input__input {
  $icon-size: 24px;

  padding-right: calc(var(--padding-inline) + #{$icon-size} + 4px);
}
</style>
