import type { FormEvent } from 'react';
import type { FormContextType, RJSFSchema, StrictRJSFSchema, WidgetProps } from '@rjsf/utils';
import {
  ariaDescribedByIds,
  enumOptionValueDecoder,
  enumOptionValueEncoder,
  enumOptionsIsSelected,
  getOptionValueFormat,
  optionId,
} from '@rjsf/utils';
import type { CheckboxProps } from 'semantic-ui-react';
import { Form, Radio } from 'semantic-ui-react';

import { getSemanticProps } from '../util';

/** The `RadioWidget` is a widget for rendering a radio group.
 *  It is typically used with a string property constrained with enum options.
 *
 * @param props - The `WidgetProps` for this component
 */
export default function RadioWidget<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(
  props: WidgetProps<T, S, F>,
) {
  const {
    id,
    htmlName,
    value,
    required,
    disabled,
    readonly,
    onChange,
    onBlur,
    onFocus,
    options,
    registry,
    uiSchema,
    rawErrors = [],
  } = props;
  const { enumOptions, enumDisabled, emptyValue } = options;
  const optionValueFormat = getOptionValueFormat(options);
  const semanticProps = getSemanticProps<T, S, F>({
    formContext: registry.formContext,
    options,
    uiSchema,
  });
  const handleChange = (_: FormEvent<HTMLInputElement>, { value: eventValue }: CheckboxProps) =>
    onChange(enumOptionValueDecoder<S>(String(eventValue!), enumOptions, optionValueFormat, emptyValue));

  const handleBlur = () => onBlur(id, value);
  const handleFocus = () => onFocus(id, value);
  const inlineOption = options.inline ? { inline: true } : { grouped: true };
  return (
    <Form.Group {...inlineOption}>
      {Array.isArray(enumOptions) &&
        enumOptions.map((option, index) => {
          const checked = enumOptionsIsSelected<S>(option.value, value);
          const itemDisabled = Array.isArray(enumDisabled) && enumDisabled.includes(option.value);
          return (
            <Form.Field
              required={required}
              control={Radio}
              id={optionId(id, index)}
              name={htmlName || id}
              {...semanticProps}
              onFocus={handleFocus}
              onBlur={handleBlur}
              onChange={handleChange}
              label={option.label}
              value={enumOptionValueEncoder(option.value, index, optionValueFormat)}
              error={rawErrors.length > 0}
              key={String(option.value)}
              checked={checked}
              disabled={disabled || itemDisabled || readonly}
              aria-describedby={ariaDescribedByIds(id)}
            />
          );
        })}
    </Form.Group>
  );
}
