import { getText } from "../../../locales/index.js";
import { _objectSpread2 } from "../../../_virtual/_@oxc-project_runtime@0.122.0/helpers/objectSpread2.js";
import { _objectWithoutProperties } from "../../../_virtual/_@oxc-project_runtime@0.122.0/helpers/objectWithoutProperties.js";
import Form from "../../form/index.js";
import useDataSource from "../hooks/useDataSource.js";
import useFormSetting from "./provider/hooks/useFormSetting.js";
import useJsonPrefixPath from "./provider/hooks/useJsonPrefixPath.js";
import useVariables from "../hooks/useVariables.js";
import DataSourceProvider from "../provider/dataSource/DataSourceProvider.js";
import useTranslationOriginal from "../../../hooks/useTranslationOriginal.js";
import React, { useEffect, useMemo } from "react";
import { isArr, isFunction, isNumber, isString } from "@pisell/utils";
import classNames from "classnames";
import { parsePhoneNumberFromString } from "libphonenumber-js";
import "./style.less";
//#region src/components/dataSourceComponents/dataSourceForm/utils.tsx
const _excluded = [
	"renderMode",
	"value",
	"onChange"
], _excluded2 = [
	"name",
	"label",
	"mode",
	"renderMode",
	"tooltip",
	"noStyle",
	"extra",
	"required",
	"requiredobj",
	"minLengthobj",
	"maxLengthobj",
	"typeobj",
	"maxobj",
	"minobj",
	"normalize",
	"getValueProps",
	"validator",
	"style",
	"validateTrigger",
	"__designMode",
	"labelCol",
	"hideLabel",
	"innerStyle"
];
/**
* @title: 增加renderMode属性
* @description: 基于renderMode属性控制渲染模式
* @return: *
* @Author: shengjie.zuo
* @Date: 2024-11-23 17:13:18
*/
const withMode = (FieldComponent, ReadPrettyComponent, transformProps) => {
	return (_ref) => {
		let { renderMode = "edit", value, onChange } = _ref, props = _objectWithoutProperties(_ref, _excluded);
		const transformedProps = (transformProps === null || transformProps === void 0 ? void 0 : transformProps(_objectSpread2(_objectSpread2({}, props), {}, {
			value,
			onChange,
			renderMode
		}), renderMode)) || _objectSpread2(_objectSpread2({}, props), {}, {
			value,
			onChange,
			renderMode
		});
		if (["view", "tableView"].includes(renderMode) && ReadPrettyComponent) return /* @__PURE__ */ React.createElement(ReadPrettyComponent, transformedProps);
		if (renderMode === "disabled") return /* @__PURE__ */ React.createElement(FieldComponent, _objectSpread2(_objectSpread2({}, transformedProps), {}, { disabled: true }));
		return /* @__PURE__ */ React.createElement(FieldComponent, transformedProps);
	};
};
/**
* @title: 追加formItem层
* @description:
* @return: *
* @Author: shengjie.zuo
* @Date: 2024-11-23 17:14:25
*/
const withFormItem = (WrappedComponent, overlayProps) => {
	return (_ref2) => {
		var _field$uiSchema;
		let { name: propsName, label: propsLabel, mode: propsMode, renderMode: propsRenderMode, tooltip, noStyle, extra, required, requiredobj, minLengthobj, maxLengthobj, typeobj, maxobj, minobj, normalize, getValueProps, validator, style, validateTrigger, __designMode, labelCol: propsLabelCol, hideLabel, innerStyle } = _ref2, otherProps = _objectWithoutProperties(_ref2, _excluded2);
		const { path: prefixPath = [] } = useJsonPrefixPath();
		const { dataSource } = useDataSource();
		const { fields } = dataSource || {};
		const { renderMode: globalRenderMode, size } = useFormSetting();
		const field = fields === null || fields === void 0 ? void 0 : fields.find((item) => item.name === propsName);
		const label = propsLabel || (field === null || field === void 0 || (_field$uiSchema = field.uiSchema) === null || _field$uiSchema === void 0 ? void 0 : _field$uiSchema.title) || propsName;
		const effectiveMode = propsRenderMode || globalRenderMode;
		const name = isString(propsName) && propsName.includes(".") ? [propsName] : propsName;
		const renderComponent = useMemo(() => {
			var _overlayProps$innerPr;
			return /* @__PURE__ */ React.createElement(WrappedComponent, _objectSpread2(_objectSpread2(_objectSpread2({}, overlayProps === null || overlayProps === void 0 ? void 0 : overlayProps.innerProps), otherProps), {}, {
				mode: propsMode,
				renderMode: effectiveMode,
				style: _objectSpread2(_objectSpread2({}, (overlayProps === null || overlayProps === void 0 || (_overlayProps$innerPr = overlayProps.innerProps) === null || _overlayProps$innerPr === void 0 ? void 0 : _overlayProps$innerPr.style) || {}), innerStyle || {}),
				fieldKey: name,
				isVerification: typeobj === null || typeobj === void 0 ? void 0 : typeobj.enabled,
				size
			}));
		}, [
			effectiveMode,
			otherProps,
			propsMode,
			overlayProps === null || overlayProps === void 0 ? void 0 : overlayProps.innerProps,
			typeobj === null || typeobj === void 0 ? void 0 : typeobj.enabled,
			size,
			innerStyle,
			name
		]);
		const isDesignMode = __designMode === "design";
		const isHidden = effectiveMode === "hidden";
		const concatName = name !== void 0 ? [...prefixPath, ...toArr(name)] : void 0;
		const rules = [];
		if (requiredobj && requiredobj.required) rules.push(_objectSpread2(_objectSpread2({}, requiredobj), {}, { message: requiredobj.message || getText("pisell-data-source-form-required-message") }));
		if (typeobj && typeobj.enabled) switch (typeobj.type) {
			case "email":
				rules.push(_objectSpread2(_objectSpread2({}, typeobj), {}, { message: typeobj.message || getText("pisell-data-source-form-email-message") }));
				break;
			case "pattern":
				rules.push(_objectSpread2(_objectSpread2({}, typeobj), {}, {
					pattern: new RegExp(typeobj.pattern),
					message: typeobj.message || getText("pisell-data-source-form-pattern-message")
				}));
				break;
			case "phone":
				rules.push({ validator: (_, originValue) => {
					var _phone;
					let value = "";
					if (isString(originValue)) value = originValue;
					else if (originValue && "phone" in originValue) value = `${(originValue === null || originValue === void 0 ? void 0 : originValue.countryCallingCode) || ""}${originValue.phone || ""}`;
					if (!(value === null || value === void 0 ? void 0 : value.trim())) {
						if ((requiredobj === null || requiredobj === void 0 ? void 0 : requiredobj.required) === false) return Promise.resolve();
						else if (typeof originValue == "object") return Promise.reject(new Error(requiredobj.message || getText("pisell-data-source-form-required-message")));
					}
					if (typeof originValue !== "string" && (requiredobj === null || requiredobj === void 0 ? void 0 : requiredobj.required) === false && (originValue === null || originValue === void 0 || (_phone = originValue.phone) === null || _phone === void 0 ? void 0 : _phone.trim()) === "") return Promise.resolve();
					try {
						const parsedNumber = parsePhoneNumberFromString(value.replace(/\s|\(|\)/g, ""));
						if (!(parsedNumber === null || parsedNumber === void 0 ? void 0 : parsedNumber.isValid())) return Promise.reject(new Error(typeobj.message || getText("pisell-data-source-form-phone-message")));
						return Promise.resolve();
					} catch (error) {
						return Promise.reject(new Error(typeobj.message || getText("pisell-data-source-form-phone-message")));
					}
				} });
				break;
			case "mobile":
				rules.push({ validator: (_, originValue) => {
					let value = "";
					if (isString(originValue)) value = originValue;
					else if (originValue && "phone" in originValue) value = `${(originValue === null || originValue === void 0 ? void 0 : originValue.countryCallingCode) || ""}${originValue.phone || ""}`;
					if (!(value === null || value === void 0 ? void 0 : value.trim())) return Promise.resolve();
					try {
						const cleanedNumber = value.replace(/\s|\(|\)/g, "");
						if (cleanedNumber.length > 15) return Promise.reject(new Error(typeobj.message || getText("pisell-data-source-form-mobile-message")));
						if (cleanedNumber.startsWith("+61")) {
							const numberWithoutPrefix = cleanedNumber.slice(3);
							if (!/^(?:04\d{8}|4\d{8})$/.test(numberWithoutPrefix)) return Promise.reject(new Error(typeobj.message || getText("pisell-data-source-form-mobile-message")));
						} else if (cleanedNumber.startsWith("+86")) {
							const numberWithoutPrefix = cleanedNumber.slice(3);
							if (!/^1[3-9]\d{9}$/.test(numberWithoutPrefix)) return Promise.reject(new Error(typeobj.message || getText("pisell-data-source-form-mobile-message")));
						}
						return Promise.resolve();
					} catch (error) {
						if (value.replace(/\s|\(|\)/g, "").length > 15) return Promise.reject(new Error(typeobj.message || getText("pisell-data-source-form-mobile-message")));
						return Promise.resolve();
					}
				} });
				break;
			case "url":
				rules.push(_objectSpread2(_objectSpread2({}, typeobj), {}, { message: typeobj.message || getText("pisell-data-source-form-url-message") }));
				break;
			case "subdomain":
				rules.push({ validator: (_, value) => {
					if (!value) return Promise.resolve();
					const subdomain = value.split(".")[0];
					if (!/^[a-z0-9-]+$/.test(subdomain)) return Promise.reject(new Error(getText("subdomain-error-pattern")));
					if (/^\d+$/.test(subdomain)) return Promise.reject(new Error(getText("subdomain-error-numbers-only")));
					if (subdomain.startsWith("-") || subdomain.endsWith("-")) return Promise.reject(new Error(getText("subdomain-error-hyphen-ends")));
					if (subdomain.includes("--")) return Promise.reject(new Error(getText("subdomain-error-consecutive-hyphens")));
					return Promise.resolve();
				} });
				break;
			case "appIdentifier":
				rules.push({ validator: (_, value) => {
					if (!value) return Promise.resolve();
					if (!/^[a-z0-9\-\._]+$/.test(value)) return Promise.reject(new Error(getText("pisell-data-source-form-app-identifier-pattern")));
					if (!/^[a-z]/.test(value)) return Promise.reject(new Error(getText("pisell-data-source-form-app-identifier-start-with-letter")));
					if (/[\-\._]$/.test(value)) return Promise.reject(new Error(getText("pisell-data-source-form-app-identifier-special-ends")));
					if (/[\-]{2,}|[\.]{2,}|[\_]{2,}/.test(value)) return Promise.reject(new Error(getText("pisell-data-source-form-app-identifier-consecutive-special")));
					return Promise.resolve();
				} });
				break;
		}
		if (maxLengthobj && maxLengthobj.enabled) rules.push({ validator(_, value) {
			let length = 0;
			if (isString(value)) length = value.length;
			else if (isArr(value)) length = value.length;
			else if (isNumber(value)) length = `${value}`.length;
			if (length > maxLengthobj.max) return Promise.reject(new Error(maxLengthobj.message || getText("pisell-data-source-form-max-length-message")(maxLengthobj === null || maxLengthobj === void 0 ? void 0 : maxLengthobj.max)));
			return Promise.resolve();
		} });
		if (minLengthobj && minLengthobj.enabled) rules.push({ validator(_, value) {
			let length = 0;
			if (isString(value)) length = value.length;
			else if (isArr(value)) length = value.length;
			else if (isNumber(value)) length = `${value}`.length;
			if (length < minLengthobj.min) return Promise.reject(new Error(minLengthobj.message || getText("pisell-data-source-form-min-length-message")(minLengthobj === null || minLengthobj === void 0 ? void 0 : minLengthobj.min)));
			return Promise.resolve();
		} });
		if (maxobj && maxobj.enabled) rules.push(_objectSpread2(_objectSpread2({}, maxobj), {}, {
			type: "number",
			message: maxobj.message || getText("pisell-data-source-form-max-value-message")(maxobj === null || maxobj === void 0 ? void 0 : maxobj.max)
		}));
		if (minobj && minobj.enabled) rules.push(_objectSpread2(_objectSpread2({}, minobj), {}, {
			type: "number",
			message: minobj.message || getText("pisell-data-source-form-min-value-message")(minobj === null || minobj === void 0 ? void 0 : minobj.min)
		}));
		if (validator) rules.push({ validator: (_, value) => {
			return validator(value);
		} });
		const labelCol = useMemo(() => {
			if (hideLabel) return { span: 0 };
			return propsLabelCol;
		}, [hideLabel, propsLabelCol]);
		const otherFormItemProps = useMemo(() => {
			if (isFunction(overlayProps === null || overlayProps === void 0 ? void 0 : overlayProps.otherFormItemProps)) return overlayProps === null || overlayProps === void 0 ? void 0 : overlayProps.otherFormItemProps(otherProps, { rules });
			return _objectSpread2(_objectSpread2(_objectSpread2({}, otherProps || {}), (overlayProps === null || overlayProps === void 0 ? void 0 : overlayProps.otherFormItemProps) || {}), {}, { onChange: void 0 });
		}, [overlayProps === null || overlayProps === void 0 ? void 0 : overlayProps.otherFormItemProps, otherProps]);
		return /* @__PURE__ */ React.createElement(Form.Item, _objectSpread2({
			required,
			style: _objectSpread2(_objectSpread2({ width: "100%" }, style), {}, { opacity: isDesignMode && isHidden ? "0.3" : 1 }),
			name: concatName,
			label,
			tooltip,
			noStyle,
			extra,
			hidden: isHidden && !isDesignMode,
			rules,
			normalize,
			getValueProps,
			validateTrigger: validateTrigger || ["onChange", "onBlur"],
			labelCol,
			initialValue: otherProps === null || otherProps === void 0 ? void 0 : otherProps.defaultValue,
			className: classNames("pisell-data-source-form-item", { "pisell-data-source-form-item-view": effectiveMode === "view" })
		}, otherFormItemProps), renderComponent);
	};
};
const withDataSource = (WrappedComponent) => {
	return (props) => {
		const { dataSource, extraParams } = props;
		return /* @__PURE__ */ React.createElement(DataSourceProvider, {
			dataSource,
			extraParams: { list: extraParams },
			requestOptions: { list: { cacheKey: `${dataSource === null || dataSource === void 0 ? void 0 : dataSource.headerDataSource}-${dataSource === null || dataSource === void 0 ? void 0 : dataSource.name}-${dataSource === null || dataSource === void 0 ? void 0 : dataSource.tableName}` } }
		}, /* @__PURE__ */ React.createElement(WrappedComponent, props));
	};
};
const withOptions = (WrappedComponent) => {
	return (props) => {
		var _list$data2;
		const translationOriginal = useTranslationOriginal();
		const { options: propsOptions, optionSourceType, labelField, valueField, extraParams } = props;
		const { parseVariable } = useVariables();
		const { list, getCurrentRecord } = useDataSource();
		const parseParams = useMemo(() => {
			const params = {};
			if (extraParams) Object.keys(extraParams).forEach((key) => {
				params[key] = parseVariable === null || parseVariable === void 0 ? void 0 : parseVariable(extraParams[key], { currentRecord: getCurrentRecord() });
			});
			return params;
		}, [extraParams]);
		useEffect(() => {
			if (optionSourceType === "api") list.run(_objectSpread2({
				page: 1,
				pageSize: 500
			}, parseParams));
		}, []);
		const options = useMemo(() => {
			var _list$data, _list$data$filter;
			if (optionSourceType !== "api") return propsOptions;
			return (((_list$data = list.data) === null || _list$data === void 0 || (_list$data = _list$data.data) === null || _list$data === void 0 || (_list$data$filter = _list$data.filter) === null || _list$data$filter === void 0 ? void 0 : _list$data$filter.call(_list$data, (item) => ![
				"draft",
				"inactive",
				"disabled"
			].includes(item === null || item === void 0 ? void 0 : item.status))) || []).map((item) => ({
				label: translationOriginal(item[labelField]),
				value: item[valueField]
			})) || [];
		}, [
			propsOptions,
			optionSourceType,
			list === null || list === void 0 || (_list$data2 = list.data) === null || _list$data2 === void 0 ? void 0 : _list$data2.data
		]);
		return /* @__PURE__ */ React.createElement(WrappedComponent, _objectSpread2(_objectSpread2({}, props), {}, { options }));
	};
};
const getNestedValue = (obj, path) => {
	const keys = path.split(".");
	let value = obj;
	for (const k of keys) {
		if (!value) break;
		value = value[k];
	}
	return value;
};
const renderValueWithMap = (value, valueMap, renderMode) => {
	const textStyle = renderMode === "tableView" ? {
		fontSize: 14,
		fontWeight: 400
	} : {};
	if (isArr(value)) return /* @__PURE__ */ React.createElement("span", { className: "pisell-form-read-pretty-text" }, value.map((item, index) => /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("span", {
		key: item,
		className: "pisell-form-read-pretty-value",
		style: textStyle
	}, valueMap === null || valueMap === void 0 ? void 0 : valueMap[item]), index < value.length - 1 && ", ")));
	else if (isString(value) || isNumber(value)) return /* @__PURE__ */ React.createElement("span", { className: "pisell-form-read-pretty-text" }, /* @__PURE__ */ React.createElement("span", {
		className: "pisell-form-read-pretty-value",
		style: textStyle
	}, (valueMap === null || valueMap === void 0 ? void 0 : valueMap[value]) || value));
	return null;
};
function toArr(str) {
	return Array.isArray(str) ? str : [str];
}
const systemFields = [
	"createdAt",
	"updatedAt",
	"createdBy",
	"created_at",
	"updated_at",
	"deleted_at"
];
const filterSystemFields = (params) => {
	return Object.keys(params).reduce((acc, key) => {
		if (!systemFields.includes(key)) acc[key] = params[key];
		return acc;
	}, {});
};
const transformFormObjToArrayWithUntouched = (obj) => {
	return Object.keys(obj).reduce((acc, key) => {
		acc.push({
			name: key,
			value: obj[key],
			touched: false
		});
		return acc;
	}, []);
};
const setFormFieldsUntouched = (form) => {
	const fields = form.getFieldsError().map((item) => {
		return {
			name: item.name,
			value: form.getFieldValue(item.name),
			touched: false
		};
	});
	form.setFields(fields);
};
//#endregion
export { filterSystemFields, getNestedValue, renderValueWithMap, setFormFieldsUntouched, toArr, transformFormObjToArrayWithUntouched, withDataSource, withFormItem, withMode, withOptions };
