import { getClassNames } from '@websolutespa/bom-core';
import { FormControl, useControl } from '@websolutespa/bom-mixer-forms';
import { useLabel } from '@websolutespa/bom-mixer-hooks';
import { ChangeEvent, FocusEvent, ReactNode, useEffect, useId, useRef, useState } from 'react';
import { Field, Input, InputProps, Label } from '../forms';
import { FieldError } from './field-error';

export const INPUT_TYPES = Object.fromEntries(
  ['button', 'checkbox', 'color', 'date', 'datetime-local', 'email', 'file', 'hidden', 'image', 'month', 'number', 'password', 'radio', 'range', 'reset', 'search', 'submit', 'tel', 'text', 'time', 'url', 'week'].map(k => [k,k])
);

type FieldTextProps = InputProps & {
  control: FormControl;
  before?: ReactNode;
  after?: ReactNode;
};

export function FieldText({ control, before, after, ...props }: FieldTextProps) {
  const uid = useId();
  const label = useLabel();

  const uniqueName = `${control.name}-${uid}`;

  const [state, setValue, setTouched] = useControl<string>(control);

  const [focus, setFocus] = useState(false);

  const ref = useRef<HTMLInputElement>(null);

  useEffect(() => {
    const onChange = (value: any) => {
      if (focus) {
        return;
      }
      if (ref.current) {
        ref.current.value = value;
      }
      // console.log('FieldText.onChange', ref.current, value);
    };
    // control.on('change', onChange);
    return () => control.off('change', onChange);
  }, [control, focus]);

  const onChange = (event: ChangeEvent<HTMLInputElement>) => {
    // console.log('FieldText', event.target.value);
    setValue(event.target.value);
    // control.value = event.target.value;
  };

  const onBlur = (_: FocusEvent<HTMLInputElement>) => {
    setTouched();
    setFocus(false);
  };

  const onFocus = (_: FocusEvent<HTMLInputElement>) => {
    setFocus(true);
  };

  const type = INPUT_TYPES[control.schema] || 'text';
  const controlLabel = control.label && label(control.label);
  return (
    state.flags.hidden ? (
      <input type="hidden" value={state.value || ''} />
    ) : (
      <Field state={state} className={getClassNames({ required: control.required && !control.disabled })}>
        {controlLabel && (
          <Label htmlFor={uniqueName}>
            {controlLabel}
          </Label>
        )}

        <Input
          width="100%"
          {...props}
          ref={ref}
          id={uniqueName}
          name={uniqueName}
          type={type}
          placeholder={label(control.placeholder || control.label || '')}
          defaultValue={state.value || ''}
          onChange={onChange}
          onBlur={onBlur}
          onFocus={onFocus}
          required={state.errors.some(x => x.key === 'required')}
          disabled={state.flags.disabled}
          readOnly={state.flags.readonly}
          aria-invalid={state.flags.invalid}
          aria-describedby={`${uniqueName}-error`}
          before={before}
          after={after}
          autoComplete="on"
        />

        <FieldError state={state} label={controlLabel} id={`${uniqueName}-error`} />
      </Field>
    )
  );
}
