// CPasswordInput.ts
import { defineComponent, h, ref, toRefs, watch, computed } from 'vue'
import { CFormControlWrapper } from '../form/CFormControlWrapper'

export const CPasswordInput = defineComponent({
  name: 'CPasswordInput',
  inheritAttrs: false,
  props: {
    /**
     * Accessible label for the toggle visibility button.
     */
    ariaLabelToggler: {
      type: String,
      default: 'Toggle password visibility',
    },

    /**
     * Delay emitting `change` and `update:modelValue` events.
     * `true` = 500ms delay, or specify custom delay in ms.
     */
    delay: {
      type: [Boolean, Number],
      default: false,
    },

    /**
     * Disables the password input field. When `true`, the user cannot interact with the field.
     */
    disabled: Boolean,

    /**
     * General feedback text shown below the input.
     */
    feedback: String,

    /**
     * Feedback text shown when input is invalid.
     */
    feedbackInvalid: String,

    /**
     * Feedback text shown when input is valid.
     */
    feedbackValid: String,

    /**
     * Class for the floating label wrapper.
     */
    floatingClassName: String,

    /**
     * Floating label text.
     */
    floatingLabel: String,

    /**
     * ID of the input element.
     */
    id: String,

    /**
     * Marks the input as invalid.
     */
    invalid: Boolean,

    /**
     * Main label for the input.
     */
    label: String,

    /**
     * The current value of the password input, used with v-model.
     */
    modelValue: String,

    /**
     * Makes the input read-only, allowing text selection only.
     */
    readOnly: Boolean,

    /**
     * Controls the initial visibility of the password.
     */
    showPassword: Boolean,

    /**
     * Sets the visual size of the input. Accepts `'sm'`, `'lg'`, or undefined.
     */
    size: {
      type: String as () => 'sm' | 'lg' | undefined,
      default: undefined,
    },

    /**
     * Helper or hint text displayed below the input.
     */
    text: String,

    /**
     * Enables tooltip-style validation feedback messages.
     */
    tooltipFeedback: Boolean,

    /**
     * Marks the input as valid.
     */
    valid: Boolean,

    /**
     * Alternative to `modelValue`, mostly for manual `:value` binding.
     */
    value: String,
  },
  emits: ['update:modelValue', 'change'],
  setup(props, { emit, attrs }) {
    const { delay, showPassword, size, invalid, valid } = toRefs(props)

    const localValue = ref(props.modelValue ?? props.value ?? '')
    const visible = ref(showPassword.value ?? false)

    const inputType = computed(() => (visible.value ? 'text' : 'password'))

    watch(
      () => props.modelValue ?? props.value,
      (val) => {
        if (val !== localValue.value) {
          localValue.value = val as string
        }
      }
    )

    let timeout: ReturnType<typeof setTimeout>
    watch(localValue, (val) => {
      if (delay.value) {
        clearTimeout(timeout)
        timeout = setTimeout(
          () => {
            emit('update:modelValue', val)
            emit('change', val)
          },
          typeof delay.value === 'number' ? delay.value : 500
        )
      } else {
        emit('update:modelValue', val)
        emit('change', val)
      }
    })

    const togglePassword = () => {
      visible.value = !visible.value
    }

    return () =>
      h(
        CFormControlWrapper,
        {
          describedby: attrs['aria-describedby'] as string,
          feedback: props.feedback,
          feedbackInvalid: props.feedbackInvalid,
          feedbackValid: props.feedbackValid,
          floatingClassName: props.floatingLabel
            ? ['form-password', props.floatingClassName].join(' ')
            : props.floatingClassName,
          floatingLabel: props.floatingLabel,
          id: props.id,
          invalid: props.invalid,
          label: props.label,
          text: props.text,
          tooltipFeedback: props.tooltipFeedback,
          valid: props.valid,
        },
        {
          default: () => {
            const inputEl = h('input', {
              ...attrs,
              id: props.id,
              type: inputType.value,
              class: [
                'form-control',
                {
                  [`form-control-${size.value}`]: size.value,
                  'is-invalid': invalid.value,
                  'is-valid': valid.value,
                },
                attrs.class,
              ],
              value: localValue.value,
              onInput: (e: Event) => {
                localValue.value = (e.target as HTMLInputElement).value
              },
              disabled: props.disabled,
              readOnly: props.readOnly,
            })

            const buttonEl = h(
              'button',
              {
                type: 'button',
                class: 'form-password-action',
                'data-coreui-toggle': 'password',
                'aria-label': props.ariaLabelToggler,
                onClick: togglePassword,
              },
              [h('span', { class: 'form-password-action-icon' })]
            )

            const content = [inputEl, buttonEl]

            return props.floatingLabel ? content : h('div', { class: 'form-password' }, content)
          },
        }
      )
  },
})
