import React, { useRef } from 'react'
import { useField, FieldRenderProps, UseFieldConfig } from 'react-final-form'

import { classNames } from '../utils/css'
import { InlineError } from '../InlineError/InlineError'

import '../tailwind.css'

export interface CheckboxProps {
  /** Checkbox is selected. `indeterminate` shows a horizontal line in the checkbox */
  checked?: boolean | 'indeterminate'
  /* Initial value for the input */
  value?: string
  /* Additional hint text to display */
  helpText?: string
  /* Label for the input */
  label?: string | React.ReactNode
  /* Disable the input */
  disabled?: boolean
  /* Name of the input */
  name: string
  /** Callback when checkbox is toggled */
  onChange?(newChecked: boolean): void
  /* Validation function */
  validate?: UseFieldConfig<string>['validate']
}

const styles = {
  base: 'focus:ring-primary h-4 w-4 text-link-text border-secondary-border rounded',
  default: 'text-primary-text',
  error: 'text-negative-text border-negative-border',
  disabled: 'text-disabled-text'
}

export const Checkbox = ({
  value,
  disabled,
  checked,
  label,
  helpText,
  name,
  validate,
  onChange
}: CheckboxProps) => {
  const {
    input,
    meta: { error, touched, submitError }
  }: FieldRenderProps<string> = useField(name, {
    initialValue: value,
    validate: validate,
    type: 'checkbox'
  })

  const errorText = touched && (error || submitError) ? error : null

  const inputNode = useRef<HTMLInputElement>(null)
  const isIndeterminate = checked === 'indeterminate'
  const isChecked = !isIndeterminate && Boolean(checked)

  const className = classNames(
    styles.base,
    !errorText && styles.default,
    errorText && styles.error,
    disabled && styles.disabled
  )

  const helpTextMarkup = helpText && (
    <div className="mt-2 text-sm text-secondary-text">{helpText}</div>
  )
  const errorMarkup = errorText && typeof error !== 'boolean' && (
    <div className="mt-2">
      <InlineError message={error} />
    </div>
  )

  const handleOnClick = () => {
    if (onChange == null || inputNode.current == null || disabled) {
      return
    }

    onChange(inputNode.current.checked)
    inputNode.current.focus()
  }

  return (
    <>
      <fieldset>
        <div className="relative flex items-start">
          <div className="flex h-5 items-center">
            <input
              ref={inputNode}
              id={name}
              checked={isChecked}
              type="checkbox"
              className={className}
              disabled={disabled}
              onClick={handleOnClick}
              {...input}
            />
          </div>
          <div className="ml-3 text-sm">
            <label htmlFor={name} className="font-base text-primart-text">
              {label}
            </label>
            {helpTextMarkup}
          </div>
        </div>
        {errorMarkup}
      </fieldset>
    </>
  )
}
