import type React from 'react';
import type { TextFieldProps as MuiTextFieldProps } from '@mui/material';
import { TextField as MuiTextField } from '@mui/material';
import { isFunction, isString } from 'lodash';

import { useDefaultProps } from '../../hooks';
import { isRtlText } from '../../utils';

export type TextFieldProps<Nullable extends boolean = true> = Omit<MuiTextFieldProps, 'onChange'> & {
	/**
	 * Automatically sets the text direction based on the user's input language
	 * @default true
	 */
	autoDirection?: boolean;
	/**
	 * When enabled, an empty string input ("") will be treated as a null value for the field
	 * @default true
	 */
	nullable?: Nullable;
	/**
	 * Enables automatic trimming of the input value when the field loses focus (on blur).
	 * This means leading and trailing whitespace will be removed.
	 *
	 * @default true
	 */
	trim?: boolean;
	onChange?: (
		value: Nullable extends true ? string | null : string,
		event: React.ChangeEvent<HTMLTextAreaElement | HTMLInputElement>
	) => void;
};

function TextField<Nullable extends boolean>(inProps: TextFieldProps<Nullable>) {
	const {
		value,
		type = 'text',
		onChange,
		onBlur,
		slotProps,
		autoDirection = true,
		nullable = true,
		trim = true,
		...props
	} = useDefaultProps({ name: 'RemateTextField', props: inProps });

	const onChangeHandler = (e: React.ChangeEvent<HTMLInputElement>) => {
		let value: string | null = e.target.value;

		if (e.target.value === '' && nullable) {
			value = null;
		}

		onChange?.(value as any, e);
	};

	const onBlurHandler = (e: React.FocusEvent<HTMLInputElement>) => {
		if (trim && isString(e.target.value) && e.target.value.length > 0 && /^\s+|\s+$/.test(e.target.value)) {
			let value: string | null = e.target.value.trim();

			if (value === '' && nullable) {
				value = null;
			}

			onChange?.(value as any, e);
		}

		onBlur?.(e);
	};

	return (
		<MuiTextField
			fullWidth
			{...props}
			value={value ?? ''}
			type={type}
			onChange={onChangeHandler}
			onBlur={onBlurHandler}
			slotProps={{
				...(autoDirection && {
					htmlInput: (ownerState) => {
						const value = ownerState.value as string;

						return {
							...(value?.length && { dir: isRtlText(value) ? 'rtl' : 'ltr' }),
							...(isFunction(slotProps?.htmlInput) ? slotProps?.htmlInput(ownerState) : slotProps?.htmlInput)
						};
					}
				}),
				...slotProps
			}}
		/>
	);
}

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

export default TextField;
