import { useEffect, useState } from "react";

import { IconAction, Tooltip } from "@ax/components";
import { getValidity } from "@ax/forms";
import { getFieldByPath, isEmptyContainer } from "@ax/helpers";
import type { IErrorItem } from "@ax/types";

import * as S from "./style";

const FieldsBehavior = (props: IFieldsBehaviorProps): JSX.Element => {
	const {
		value,
		fieldType,
		title,
		name,
		helptext,
		hideable,
		hideField,
		advanced,
		className,
		whiteList,
		mandatory,
		disabled,
		filled,
		validators,
		error,
		deleteError,
		editorID,
		objKey,
		inversed = false,
	} = props;

	const [showAdvanced, setShowAdvanced] = useState(false);
	const [errorField, setErrorField] = useState(false);
	const [message, setMessage] = useState(helptext);

	// biome-ignore lint/correctness/useExhaustiveDependencies: TODO: fix this
	useEffect(() => {
		setErrorField(false);
		setMessage(helptext);
		if (error) {
			handleValidation(value);
		}
	}, [editorID, error]);

	const helpTextWrapper = message ? (
		<S.HelpText error={errorField} inversed={inversed}>
			{message}
		</S.HelpText>
	) : (
		<></>
	);

	const isComponentArray = fieldType === "ComponentArray" || fieldType === "FormFieldArray";
	const isComponentContainer = fieldType === "ComponentContainer";
	const isFormContainer = fieldType === "FormContainer";
	const hasMultipleOptions: boolean = (!!whiteList && whiteList.length > 1) || isFormContainer;

	const hasTitle = !!title && !isComponentArray;
	const Field = getFieldByPath(fieldType);

	const toggleAdvanced = () => setShowAdvanced(!showAdvanced);

	const containerInfo = isComponentContainer && !!value && isEmptyContainer(value, hasMultipleOptions);

	const isEmpty = containerInfo ? containerInfo.isEmpty : false;
	const showTitle = hasTitle && (!isEmpty || hasMultipleOptions);

	const Asterisk = () => (mandatory ? <S.Asterisk>*</S.Asterisk> : null);

	const wrapperClass = filled ? `${className} filled` : className;

	const handleValidation = (newValue: string | any[], fieldValidators?: Record<string, unknown>) => {
		const validatorWithErrors = error ? { ...validators, ...error.validator } : validators;
		const allValidators = fieldValidators ? { ...validatorWithErrors, ...fieldValidators } : validatorWithErrors;
		const { isValid, errorText } = getValidity(allValidators, newValue);
		if (isValid) {
			setMessage(helptext);
			error && deleteError && deleteError(error);
		} else {
			setMessage(errorText);
		}
		setErrorField(!isValid);
	};

	const resetValidation = () => {
		setMessage(helptext);
		error && deleteError && deleteError(error);
		setErrorField(false);
	};

	return (
		<S.Wrapper className={wrapperClass} showTitle={showTitle} id={`gdd_${objKey}`}>
			<S.Content error={errorField} inversed={inversed} data-testid="fields-behavior-wrapper">
				<Field
					{...props}
					showAdvanced={showAdvanced}
					handleValidation={handleValidation}
					resetValidation={resetValidation}
					error={errorField}
				/>
			</S.Content>
			<S.Header className="fieldHeader">
				{showTitle && (
					<S.Label htmlFor={name} error={errorField} inversed={inversed}>
						{title} <Asterisk />
					</S.Label>
				)}
				<S.Icons>
					{hideable && !isEmpty && (
						<Tooltip content="Hide">
							<IconAction icon="delete" size="s" onClick={hideField} disabled={disabled} />
						</Tooltip>
					)}
					{advanced && (
						<Tooltip content="Options">
							<IconAction icon="settings" size="s" onClick={toggleAdvanced} disabled={disabled} />
						</Tooltip>
					)}
				</S.Icons>
			</S.Header>
			{helpTextWrapper}
		</S.Wrapper>
	);
};

interface IFieldsBehaviorProps {
	value: any;
	fieldType: string;
	title?: string;
	name?: string;
	helptext?: string;
	hideable?: boolean;
	hideField?: () => void;
	advanced?: boolean;
	className?: string;
	whiteList?: string[];
	mandatory?: boolean;
	disabled?: boolean;
	filled?: boolean;
	validators?: Record<string, unknown>;
	error?: any; // TODO add type IErrorItem?
	deleteError?: (error: IErrorItem) => void;
	editorID?: string | number;
	objKey?: string | number;
	inversed?: boolean;
	[key: string]: unknown;
}

export default FieldsBehavior;
