import { useFormContext, useFormControl } from 'domains/forms/hooks'
import { InputHTMLAttributes } from 'preact/compat'
import { useRef, useLayoutEffect } from 'preact/hooks'
import FormControlWrapper from './wrapper'

type InputProps = InputHTMLAttributes<HTMLInputElement> & {
  name: 'textMessageEntry'
  labelText: string
  labelClass: string
  contentHint?: string | null
  focus?: boolean
}

function Input({
  id,
  name,
  type,
  labelText,
  labelClass,
  contentHint = null,
  focus,
  'aria-invalid': ariaInvalid,
  'aria-describedby': ariaDescribedBy,
  ...props
}: InputProps) {
  const inputRef = useRef<HTMLInputElement | null>(null)
  const { isSubmitted } = useFormContext()
  const [field, { error }] = useFormControl(name)
  const hasError = isSubmitted && error

  const describedByIds: InputHTMLAttributes<HTMLInputElement>['aria-describedby'][] =
    []
  if (ariaDescribedBy) {
    describedByIds.push(ariaDescribedBy)
  }
  if (contentHint) {
    describedByIds.push(`${id}-content-hint`)
  }
  if (hasError) {
    describedByIds.push(`${id}-error`)
  }

  useLayoutEffect(() => {
    if (inputRef.current && focus) {
      inputRef.current.focus()
    }
  }, [focus])

  // todo: destructure Field
  return (
    <FormControlWrapper
      id={id}
      contentHint={contentHint}
      validity={!hasError}
      errorText={error}
      labelText={labelText}
      labelClass={labelClass}
    >
      <input
        {...field}
        {...props}
        ref={inputRef}
        id={id}
        type={type}
        aria-invalid={ariaInvalid || hasError ? 'true' : 'false'}
        aria-describedby={describedByIds.join(' ') || undefined}
        name={name}
      />
    </FormControlWrapper>
  )
}

export default Input
