import { h, type FunctionComponent } from 'preact'
import { useCallback, useEffect, useRef, useState } from 'preact/hooks'
import cn from 'classnames'
import mergeStyles from '../utils/merge_styles.ts'

// interface Styles {
//   base?: string
//   touched?: string
//   element?: string
//   label?: string
// }

export default function selectFactory({ styles }): FunctionComponent<{
  autoFocus?: boolean
  className?: string
  defaultValue?: string
  disabled?: boolean
  name: string
  noEmpty?: boolean
  label: string
  placeholder?: string
  required?: boolean
  options: string[] | number[] | { label: string; value: string | number }
}> {
  if (Array.isArray(styles)) {
    styles = mergeStyles(styles)
  }

  const Select = ({
    autoFocus,
    className,
    color,
    defaultValue,
    design = 'main',
    disabled,
    icon,
    name,
    label,
    noEmpty,
    onChange,
    placeholder,
    required,
    size = 'medium',
    options,
  }) => {
    const [touched, setTouched] = useState(false)
    const selectRef = useRef<HTMLSelectElement>()

    console.log(options)

    const onBlur = useCallback(() => setTouched(true), [])

    useEffect(() => {
      const form = selectRef.current!.form
      const resetTouched = setTouched.bind(null, false)

      form!.addEventListener('reset', resetTouched)

      return () => form!.removeEventListener('reset', resetTouched)
    }, [])

    useEffect(() => {
      if (autoFocus) selectRef.current!.focus()
    }, [autoFocus])

    return (
      <div
        className={cn(
          styles.base,
          design && styles[design],
          color && styles[color],
          size && styles[size],
          touched && styles.touched,
          className,
        )}
      >
        {icon && <div className={cn(styles.icon)} style={{ maskImage: icon }} />}

        <select
          autoFocus={autoFocus}
          className={styles.element}
          disabled={disabled}
          name={name}
          onBlur={onBlur}
          onChange={onChange}
          ref={selectRef}
          defaultValue={defaultValue}
          required={required}
        >
          {!noEmpty && <option value=''>{placeholder || label}</option>}

          {options &&
            options.map((option) => (
              <option
                key={option.value != null ? option.value : option}
                value={option.value != null ? option.value : option}
              >
                {option.label || option}
              </option>
            ))}
        </select>

        {/**
         * <label> comes after <input> to be able to use next sibling CSS selector
         * (see public input.module.scss). Use `flexbox` and `order` if <label> needs to be
         * displayed before <input> (see admin input.module.scss)
         */}
        {label && (
          <label className={styles.label} htmlFor={name}>
            {label}
          </label>
        )}
      </div>
    )
  }

  return Select
}
