import { FieldPath, FieldValues, useController, UseControllerProps } from 'react-hook-form';
import { isBoolean, isString } from 'lodash';

import { useDefaultProps } from '../../hooks';
import { useLocalization } from '../../localization';
import { Select } from '../select';
import { SelectOption, SelectProps } from '../select/Select';

export type RHFSelectProps<
	TFieldValues extends FieldValues = FieldValues,
	TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
	TOptions extends readonly SelectOption<any>[] = [],
	TEmptyOption extends boolean = false,
	TEmptyValue = null
> = Omit<SelectProps<TOptions, TEmptyOption, TEmptyValue>, 'value' | 'name' | 'disabled' | 'error'> &
	UseControllerProps<TFieldValues, TName>;

function RHFSelect<
	TFieldValues extends FieldValues,
	TName extends FieldPath<TFieldValues>,
	TOptions extends readonly SelectOption<any>[] = [],
	TEmptyOption extends boolean = false,
	TEmptyValue = null
>(inProps: RHFSelectProps<TFieldValues, TName, TOptions, TEmptyOption, TEmptyValue>) {
	const { translate } = useLocalization();

	const {
		/** React Hook Form */
		name,
		rules,
		control,
		disabled,
		defaultValue,
		shouldUnregister,
		/** React Hook Form */

		required,
		helperText,
		label,
		onChange,
		onBlur,
		...other
	} = useDefaultProps({ name: 'ReevolveRHFSelect', props: inProps });

	const {
		field,
		fieldState: { error }
	} = useController<TFieldValues, TName>({
		name,
		defaultValue,
		disabled,
		shouldUnregister,
		control,
		rules: rules && {
			...rules,
			required: rules?.required === true ? translate('validation.required', { label }) : rules?.required
		}
	});

	const isFieldRequired = isBoolean(rules?.required)
		? rules.required
		: isString(rules?.required) || rules?.required?.value || required;

	const onChangeHandler: SelectProps<TOptions, TEmptyOption, TEmptyValue>['onChange'] = (value, event, child) => {
		field.onChange(value);
		onChange?.(value, event, child);
	};

	const onBlurHandler = (e: React.FocusEvent<HTMLInputElement>) => {
		field.onBlur();
		onBlur?.(e);
	};

	return (
		<Select
			{...other}
			name={field.name}
			inputRef={field.ref}
			value={field.value as any}
			disabled={field.disabled}
			onChange={onChangeHandler}
			onBlur={onBlurHandler}
			label={label}
			error={!!error}
			helperText={error?.message ?? helperText}
			required={isFieldRequired}
		/>
	);
}

declare module '@mui/material' {
	interface Components {
		ReevolveRHFSelect?: {
			defaultProps?: Partial<RHFSelectProps>;
		};
	}
}

export default RHFSelect;
