import { useFormContext, useFormControl } from 'domains/forms/hooks'
import { className } from 'lib/css'
import { useCallback, useState } from 'preact/hooks'
import Icon from 'ui/components/layout/icon'
import { useGeneratedId } from 'ui/hooks/seamly-hooks'
import Error from './error'

export default function FileInput({
  id,
  name,
  labelText,
  contentHint,
  outputText,
  accept,
}) {
  const { isSubmitted } = useFormContext()
  const [focusWithin, setFocusWithin] = useState(false)
  const [{ onInput, onBlur }, { error }] = useFormControl(name)
  const errorId = useGeneratedId()
  const contentHintId = useGeneratedId()
  const outputId = useGeneratedId()
  const hasError = isSubmitted && error

  const describedByIds = [outputId]
  if (contentHint) {
    describedByIds.push(contentHintId)
  }
  if (hasError) {
    describedByIds.push(errorId)
  }

  const handleFocus = useCallback(() => {
    setFocusWithin(true)
  }, [setFocusWithin])

  const handleBlur = useCallback(() => {
    setFocusWithin(false)
    onBlur()
  }, [setFocusWithin, onBlur])

  const handleChange = useCallback(
    (e) => {
      const customEvent = {
        target: {
          value: e.target.files,
        },
      }

      onInput(customEvent)
    },
    [onInput],
  )

  return (
    <div className={className('upload__container')}>
      {contentHint && (
        <span className={className('upload__content-hint')} id={contentHintId}>
          {contentHint}
        </span>
      )}
      <Error id={errorId} error={hasError && error} />
      <div
        className={className([
          'file-upload',
          ...(focusWithin ? ['focus-within'] : []),
        ])}
      >
        <label htmlFor={id} className={className('upload__label')}>
          <Icon name="upload" size="32" alt="" />
          <div>
            <span className={className(['upload__label--text'])}>
              {labelText}
            </span>
            <input
              id={id}
              className={className('upload__input')}
              type="file"
              name={name}
              onChange={handleChange}
              aria-invalid={hasError ? 'true' : 'false'}
              aria-describedby={describedByIds.join(' ')}
              accept={accept || null}
              onFocus={handleFocus}
              onBlur={handleBlur}
            />
            <span
              className={className('upload__output')}
              aria-hidden="true"
              id={outputId}
            >
              {outputText}
            </span>
          </div>
        </label>
      </div>
    </div>
  )
}
