import { Form } from "../../utilities/form/Form.mjs";
import { SubmitButton } from "../../utilities/form/SubmitButton.mjs";
import { FormButtons } from "../../utilities/form/FormButtons.mjs";
import { getPathObject, getPrimaryKeyValues } from "../../utilities/maintenanceEngine/CrudBrowserUtilities.mjs";
import { CardinalityTypeEnums, EntityAttributeEnums, UdpEnums } from "../../enums/unitySystemEnums.mjs";
import { useHandleAxiosSnackbar } from "../../utilities/apiHelpers.mjs";
import { toLowerFirstChar } from "../../utilities/input/StringUtilities.mjs";
import { getSanitizedName } from "../../utilities/entities/entityUtilities.mjs";
import { useCrudActions } from "../../hooks/crudActions.mjs";
import { usePromotedMethodEntity } from "../../hooks/usePromotedMethodEntity.mjs";
import { executeQueryWithParameters } from "../../udp/utilities/methodUtils.mjs";
import useDefaultFormValues from "../../utilities/crud/useDefaultFormValues.mjs";
import { TagEnums } from "../../enums/tagEnums.mjs";
import { UdpCrudFormFields } from "./UdpCrudFormFields.mjs";
import React, { useCallback, useEffect, useMemo, useState } from "react";
import { Typography, makeStyles } from "@material-ui/core";
import PropTypes from "prop-types";
import { differenceWith } from "lodash-es";
//#region src/UI/forms/CrudForm.jsx
const useStyles = makeStyles((theme) => ({
	actions: {
		marginTop: theme.spacing(2),
		marginBottom: theme.spacing(2),
		display: "flex",
		flexDirection: "row"
	},
	title: { flexGrow: 1 },
	subject: {
		marginLeft: theme.spacing(1),
		display: "flex",
		flexDirection: "row",
		flexGrow: 1
	},
	switchRoot: { marginLeft: theme.spacing(1) },
	input: {
		height: 34,
		padding: 0
	},
	formTextInput: { fontSize: 13 },
	labelRoot: { fontSize: 13 }
}));
const CrudForm = (props) => {
	const { entityAttributes, udpFieldInfos, foreignKeyData, crudTableEditionData, closeSideSheet, onCreate, onUpdate, isNewEntry, entityData, entityName } = props;
	const { renderInputByFieldType } = useCrudActions();
	const [fkData, setFkData] = useState(foreignKeyData?.map((fkd) => ({ ...fkd })));
	const { data: promotedEntity } = usePromotedMethodEntity(entityName);
	const { data: udpTagAssocPromotedEntity } = usePromotedMethodEntity("UdpTagAssociation", true);
	const { defaultFormValues } = useDefaultFormValues(entityAttributes);
	const [crudTableFormData, setCrudTableFormData] = useState(crudTableEditionData || defaultFormValues);
	const [existingTagAssociation, setExistingTagAssociation] = useState([]);
	const classes = useStyles();
	const { handleErrorSnackbar } = useHandleAxiosSnackbar();
	const primaryKeyValues = useMemo(() => getPrimaryKeyValues(entityAttributes, crudTableEditionData), [entityAttributes, crudTableEditionData]);
	const getEntityFull = useCallback(async () => {
		if (!primaryKeyValues || !primaryKeyValues.length || !promotedEntity?.unityBaseGetFullMethod?.apiMethodId || !promotedEntity?.unityBaseUpdateMethod?.pathParameters) return null;
		const pathObject = getPathObject(promotedEntity.unityBaseUpdateMethod.pathParameters, primaryKeyValues);
		let data = { requestBody: {} };
		if (Array.isArray(pathObject)) pathObject.forEach((po) => {
			data[Object.keys(po)[0]] = po[Object.keys(po)[0]];
		});
		else data = {
			...pathObject,
			requestBody: {}
		};
		const response = await executeQueryWithParameters({ data }, promotedEntity.unityBaseGetFullMethod.apiMethodId).catch((res) => {
			console.error(res);
		});
		if (response?.status === 200) return response.data;
		else console.error(`Could not retrieve full data for ${promotedEntity?.entityName}`);
		return null;
	}, [promotedEntity, primaryKeyValues]);
	const manyToManyPropertyList = useMemo(() => {
		if (!entityAttributes?.length) return [];
		const mtmPropertyList = /* @__PURE__ */ new Set();
		entityAttributes.forEach((attr) => {
			if (attr?.extendedProperties?.childEntity) Object.keys(attr.extendedProperties.childEntityAssoc || {}).length && attr.extendedProperties.childEntityAssoc.Cardinality === CardinalityTypeEnums.Many_To_Many && attr.extendedProperties.childEntityAssoc.Keys.forEach((value, i) => {
				const name = value.split(",")[0];
				if (name) mtmPropertyList.add(name.toLowerCase());
			});
		});
		return mtmPropertyList;
	}, [entityAttributes]);
	const getJoiningObj = (schemaAttribute, ceAttributes) => {
		return ceAttributes.find((ceAttr) => Object.keys(ceAttr?.extendedProperties?.childEntityAssoc || {}).length && ceAttr.extendedProperties.childEntityAssoc.Keys.find((a) => {
			const fieldId = a.split(",")[0];
			return (/^[A-Z]*$/.test(fieldId) ? fieldId.toLowerCase() : toLowerFirstChar(fieldId)) === toLowerFirstChar(schemaAttribute.name);
		}));
	};
	const renderAttribute = useCallback((schemaAttribute_0, fieldInfo) => {
		let render = !fieldInfo?.isIdentity;
		if (schemaAttribute_0?.extendedProperties?.identifier && fieldInfo?.dataType === "Guid") render = false;
		entityAttributes.every((schemaAttribute_1, index) => {
			if (getJoiningObj(schemaAttribute_1, entityAttributes.filter((ea) => ea.extendedProperties.childEntity && ea.extendedProperties.childEntityAssoc.Cardinality === CardinalityTypeEnums.Many_To_Many && ea.extendedProperties.childEntityAssoc.IsJoiningObject))) {
				render = true;
				return false;
			}
			return true;
		});
		return render;
	}, [entityAttributes]);
	const transformDataForUdpMaintenance = useCallback((values) => {
		const sanitizedName = getSanitizedName(entityName?.toLowerCase());
		if (sanitizedName === UdpEnums.Udp_Lookup.toLowerCase()) {
			const attributeName = toLowerFirstChar(EntityAttributeEnums.Domain_Name);
			let domainName = values[attributeName];
			const modelNameSpaceStructure = domainName?.namespaceStructure?.model;
			const sanitizedName_0 = domainName?.sanitizedName;
			values[toLowerFirstChar(EntityAttributeEnums.Is_Product_Lookup)] = false;
			if (modelNameSpaceStructure) values[attributeName] = `${modelNameSpaceStructure}.Models.${sanitizedName_0}`;
			else values[attributeName] = "";
		} else if (sanitizedName === TagEnums.TagTypeSanitizedName.toLowerCase()) values[toLowerFirstChar(EntityAttributeEnums.User_Defined)] = true;
		else if (sanitizedName === UdpEnums.Udp_Shortcut_Content.toLowerCase()) values[toLowerFirstChar(EntityAttributeEnums.Is_Product_ShortcutContent)] = false;
	}, [entityName]);
	const tagAssociationComparator = (ta1, ta2) => {
		return ta1?.id === ta2?.id;
	};
	const handleTagAssociation = useCallback(async (values_0, businessObjectKey) => {
		const tagAssociationToDelete = differenceWith(existingTagAssociation, values_0?.udpTags, tagAssociationComparator);
		const tagAssociationToCreate = differenceWith(values_0?.udpTags, existingTagAssociation, tagAssociationComparator);
		const deleteTagAssociationApiMethod = udpTagAssocPromotedEntity?.unityBaseDeleteMethod;
		const createTagAssociationApiMethod = udpTagAssocPromotedEntity?.unityBaseCreateMethod;
		if (businessObjectKey) {
			if (deleteTagAssociationApiMethod) {
				const deletedPromises = [];
				tagAssociationToDelete.forEach((tagAssocToDelete) => {
					const data_0 = {};
					data_0["{tagId}"] = tagAssocToDelete.id;
					data_0["{entityBusinessKey}"] = businessObjectKey;
					deletedPromises.push(executeQueryWithParameters({ data: data_0 }, deleteTagAssociationApiMethod.apiMethodId));
				});
				await Promise.all(deletedPromises.map((p) => p.catch((e) => e))).then((responses) => {
					if (responses.length !== deletedPromises.length) console.warn(`Not all Tag Association deleted`);
				});
			} else handleErrorSnackbar(null, "Delete Tag Association Method Not Promoted");
			if (createTagAssociationApiMethod) {
				const createdPromises = [];
				tagAssociationToCreate.forEach((tagAssoc) => {
					const data_1 = { requestBody: {
						tagId: tagAssoc.id,
						entityBusinessKey: businessObjectKey
					} };
					createdPromises.push(executeQueryWithParameters({ data: data_1 }, createTagAssociationApiMethod.apiMethodId));
				});
				await Promise.all(createdPromises.map((p_0) => p_0.catch((e_0) => e_0))).then((responses_0) => {
					responses_0.forEach((response_0) => {
						if (response_0.status === 200) {
							const entityBusinessKey = response_0.data.entityBusinessKey;
							if (!tagAssociationToCreate.find((ta) => ta.value === entityBusinessKey)) console.warn(`Tag Association not created for all file to entities`);
						}
					});
				});
				setExistingTagAssociation(values_0?.udpTags);
			} else handleErrorSnackbar(null, "Create Tag Association Method Not Promoted");
		}
	}, [
		handleErrorSnackbar,
		existingTagAssociation,
		setExistingTagAssociation,
		udpTagAssocPromotedEntity
	]);
	const handleSubmit = useCallback(async (values_1) => {
		let newTableData = {
			...crudTableFormData,
			...values_1
		};
		transformDataForUdpMaintenance(newTableData);
		const isNewRow = !crudTableEditionData;
		if (!isNewEntry) entityAttributes.filter((ea_0) => {
			const joiningObject = getJoiningObj(ea_0, entityAttributes);
			const fieldInfo_0 = udpFieldInfos?.find((fi) => fi?.name.toLowerCase() === ea_0?.name?.toLowerCase());
			return ea_0?.extendedProperties?.identifier && fieldInfo_0?.isIdentity && fieldInfo_0?.dataType !== "Guid" && (!joiningObject || joiningObject.extendedProperties?.childEntity);
		}).forEach((ea_1) => {
			delete newTableData[ea_1.name];
		});
		foreignKeyData.forEach((fkd_0) => {
			Object.keys(newTableData).forEach((key) => {
				if (key === fkd_0.fieldName) {
					const fkData_0 = fkd_0.data.find((d) => d.id === newTableData[key]?.id)?.id;
					if (fkData_0 !== null) newTableData[key] = fkData_0;
				}
			});
		});
		let businessObjectKey_0 = "";
		if (isNewRow) {
			if (onCreate) {
				const createdResponse = await onCreate(newTableData);
				if (createdResponse?.status === 200) businessObjectKey_0 = createdResponse?.data?.businessObjectKey;
			}
		} else if (onUpdate) {
			await onUpdate(newTableData, primaryKeyValues);
			businessObjectKey_0 = newTableData?.businessObjectKey;
		}
		if (businessObjectKey_0 && values_1?.udpTags) handleTagAssociation(values_1, businessObjectKey_0);
		closeSideSheet && closeSideSheet();
	}, [
		crudTableFormData,
		transformDataForUdpMaintenance,
		crudTableEditionData,
		isNewEntry,
		foreignKeyData,
		closeSideSheet,
		entityAttributes,
		onCreate,
		onUpdate,
		primaryKeyValues,
		handleTagAssociation
	]);
	const shouldAttributeRenderField = useCallback((schemaAttribute_2) => {
		const sanitizedName_1 = getSanitizedName(entityName?.toLowerCase());
		if (sanitizedName_1 === TagEnums.TagTypeSanitizedName.toLowerCase() && schemaAttribute_2?.name === toLowerFirstChar(EntityAttributeEnums.User_Defined)) return false;
		else if (sanitizedName_1 === UdpEnums.Udp_Shortcut_Content.toLowerCase() && schemaAttribute_2?.name === toLowerFirstChar(EntityAttributeEnums.Is_Product_ShortcutContent)) return false;
		else if (sanitizedName_1 === UdpEnums.Udp_Lookup.toLowerCase() && schemaAttribute_2?.name === toLowerFirstChar(EntityAttributeEnums.Is_Product_Lookup)) return false;
		return true;
	}, [entityName]);
	useEffect(() => {
		const getFullData = async () => {
			const fullEntityData = await getEntityFull();
			if (fullEntityData) {
				const filteredTags = fullEntityData.udpTags?.map((tagAssoc_0) => tagAssoc_0.udpTagAssociationUdpTag);
				setExistingTagAssociation(filteredTags || []);
			}
		};
		if (promotedEntity && !isNewEntry) getFullData();
	}, [
		promotedEntity,
		getEntityFull,
		isNewEntry
	]);
	useEffect(() => {
		if (foreignKeyData) setFkData(foreignKeyData?.map((fkd_1) => ({ ...fkd_1 })));
	}, [foreignKeyData]);
	return /* @__PURE__ */ React.createElement(Form, { onSubmit: handleSubmit }, /* @__PURE__ */ React.createElement("div", null, entityAttributes?.map((schemaAttribute_3, index_0) => {
		const fieldInfo_1 = udpFieldInfos?.find((fi_0) => fi_0?.name.toLowerCase() === schemaAttribute_3?.name?.toLowerCase());
		if (fieldInfo_1?.isPrimaryKey && !isNewEntry) schemaAttribute_3.disabled = true;
		if (fieldInfo_1?.isPrimaryKey && isNewEntry && !fieldInfo_1?.isIdentity) schemaAttribute_3.disabled = false;
		if (!shouldAttributeRenderField(schemaAttribute_3)) return null;
		return renderAttribute(schemaAttribute_3, fieldInfo_1) && /* @__PURE__ */ React.createElement(React.Fragment, { key: `${schemaAttribute_3.name}-${index_0}` }, /* @__PURE__ */ React.createElement(Typography, {
			variant: "subtitle2",
			style: { marginTop: 8 }
		}, schemaAttribute_3.friendlyName), renderInputByFieldType(schemaAttribute_3, index_0, entityAttributes, fieldInfo_1, fkData, setFkData, crudTableFormData, classes, isNewEntry, entityData, manyToManyPropertyList));
	}), /* @__PURE__ */ React.createElement(UdpCrudFormFields, {
		entityName,
		formData: crudTableFormData,
		existingTagAssociation
	})), /* @__PURE__ */ React.createElement(FormButtons, null, /* @__PURE__ */ React.createElement(SubmitButton, {
		id: "udpRecord-CrudForm-Submit",
		udprecordid: "udpRecord-CrudForm-Submit",
		variant: "contained",
		color: "secondary",
		disablePristine: false,
		disabled: false,
		style: { marginTop: 15 }
	}, "Save")));
};
CrudForm.propTypes = {
	entityAttributes: PropTypes.array,
	foreignKeyData: PropTypes.array,
	crudTableEditionData: PropTypes.array,
	closeSideSheet: PropTypes.func,
	onCreate: PropTypes.func,
	onUpdate: PropTypes.func
};
//#endregion
export { CrudForm };

//# sourceMappingURL=CrudForm.mjs.map