import type { AttributeClazz } from '../AttributeTypes';
import type { BaseAttributeType } from './BaseAttributeType';
export interface BaseAttribute {
	code: string;
	available: boolean | null;
	attributeType: BaseAttributeType;
	attributeClazz: AttributeClazz;
	childAttributes: BaseAttribute[];
	label: string;
	hint: string;
	approvalRequired: boolean;
	additionalInfo: unknown | null;
	defaultValueExpr: string | null;
	fixReadOnlyValue: boolean;
	fixReadOnlyValueExpr: string | null;
	hidden: boolean;
	validationRules: unknown | null;
	visibilityExpr: string | null;
	availabilityExpr: string | null;
	restrictPropagations: Array<{ name: string; id: string }>;
	defaultValue: unknown;

	// Динамические поля, который добавляются при работе формой.
	// TODO: Вынести на уровень работы с редактированием ковенанта

	/** Состояние сброса атрибута */
	attributeWasReset?: boolean;
	/** Индекс атрибута в поле partyList атрибута PartyListAttribute */
	listElementIndex?: number;
}
import type { Attribute } from '$conditions-core';

import {
	checkIsAmount,
	checkIsBoolean,
	checkIsCurrency,
	checkIsDateWithoutYear,
	checkIsNumeric,
	checkIsPartyList,
	checkIsPercentage,
	checkIsScalar,
	checkIsSelect,
} from '../attributeTypeGuards';

/**
 * @description Построение узла XML-дерева по значению атрибута
 * @param { String } xmlTreeString XML-описание атрибута в виде строки
 * @param { Object } attribute Объект атрибута условия
 *
 * @returns Строковые описания атрибутов в виде xml
 *  */
export const addAttributeAsNodeStrToXmlTreeStr = (
	xmlTreeString: string,
	attribute: Attribute,
): string => {
	if (!attribute.available) {
		return xmlTreeString;
	}

	const { code } = attribute;

	if (checkIsNumeric(attribute)) {
		const newNode = `<${code}>${attribute.numeric ?? ''}</${code}>`;

		return xmlTreeString + newNode;
	}

	if (checkIsAmount(attribute)) {
		const { amount, currency } = attribute;

		const amountNode = `<amount>${amount ?? ''}</amount>`;
		const currencyNode = `<currency>${currency ?? ''}</currency>`;

		const newNode = `<${code}>${amountNode}${currencyNode}</${code}>`;

		return xmlTreeString + newNode;
	}

	if (checkIsBoolean(attribute) && attribute.booleanValue) {
		const children = attribute.childAttributes.reduce(addAttributeAsNodeStrToXmlTreeStr, '');
		const newNode = `<${code}>${children}</${code}>`;

		return xmlTreeString + newNode;
	}

	if (checkIsPercentage(attribute)) {
		const newNode = `<${code}>${attribute.percent ?? ''}</${code}>`;

		return xmlTreeString + newNode;
	}

	if (checkIsScalar(attribute)) {
		const newNode = `<${code}>${attribute.scalar ?? ''}</${code}>`;

		return xmlTreeString + newNode;
	}

	if (checkIsDateWithoutYear(attribute)) {
		const { day, month } = attribute;

		const newNode = `<${code}><day>${day ?? ''}</day><month>${month ?? ''}</month></${code}>`;

		return xmlTreeString + newNode;
	}

	if (checkIsCurrency(attribute)) {
		const newNode = `<${code}>${attribute.currency ?? ''}</${code}>`;

		return xmlTreeString + newNode;
	}

	if (checkIsSelect(attribute) && attribute.selectedOption) {
		const children = (attribute.selectedOption.childAttributes || []).reduce(
			addAttributeAsNodeStrToXmlTreeStr,
			'',
		);
		const newNode = `<${code}><${attribute.selectedOption.code}>${children}</${attribute.selectedOption.code}></${code}>`;

		return xmlTreeString + newNode;
	}

	if (checkIsPartyList(attribute)) {
		const { partyList } = attribute;

		const partyNodes = (partyList || []).map((party) => {
			const children = (party.childAttributes || []).reduce(addAttributeAsNodeStrToXmlTreeStr, '');

			return `<item id='$conditions-constructor-v2/{party.id}' index='$conditions-constructor-v2/{index}'>${children}</item>`;
		});

		const newNode = `<${code}>${partyNodes}</${code}>`;

		return xmlTreeString + newNode;
	}

	return xmlTreeString;
};
напиши тесты на ф-ю