import { createContext, useCallback, useContext, useEffect, useMemo, useState } from "react";
import { reaction, useField, useFieldSchema } from "@tachybase/schema";
import { flatten, getValuesByPath } from "@tachybase/utils/client";
import lodash, { isString } from "lodash";
import cloneDeep from "lodash/cloneDeep";
import { useCollectionManager_deprecated, useCollection_deprecated } from "../../../collection-manager/index.mjs";
import { isInFilterFormBlock } from "../../../filter-provider/index.mjs";
import { mergeFilter } from "../../../filter-provider/utils.mjs";
import { useRecord } from "../../../record-provider/index.mjs";
import { useParseDataScopeFilter } from "../../../schema-settings/index.mjs";
import { DEBOUNCE_WAIT } from "../../../variables/index.mjs";
import { getPath } from "../../../variables/utils/getPath.mjs";
import { getVariableName } from "../../../variables/utils/getVariableName.mjs";
import { isVariable } from "../../../variables/utils/isVariable.mjs";
import { useDesignable } from "../../hooks/index.mjs";
import { AssociationFieldContext } from "./context.mjs";
const useInsertSchema = (component)=>{
    const fieldSchema = useFieldSchema();
    const { insertAfterBegin } = useDesignable();
    const insert = useCallback((ss)=>{
        const schema = fieldSchema.reduceProperties((buf, s)=>{
            if (s['x-component'] === 'AssociationField.' + component) return s;
            return buf;
        }, null);
        if (!schema) insertAfterBegin(cloneDeep(ss));
    }, [
        component
    ]);
    return insert;
};
function useAssociationFieldContext() {
    return useContext(AssociationFieldContext);
}
function useServiceOptions(props) {
    var _field_componentProps_service_params, _field_componentProps_service, _field_componentProps, _service_params;
    const { action = 'list', service, useOriginalFilter } = props;
    const fieldSchema = useFieldSchema();
    const field = useField();
    const { getField } = useCollection_deprecated();
    const { getCollectionJoinField } = useCollectionManager_deprecated();
    const record = useRecord();
    const { parseFilter, findVariable } = useParseDataScopeFilter();
    const [fieldServiceFilter, setFieldServiceFilter] = useState(null);
    useEffect(()=>{
        var _fieldSchema_xcomponentprops_service_params, _fieldSchema_xcomponentprops_service, _fieldSchema_xcomponentprops, _field_componentProps_service_params, _field_componentProps_service, _field_componentProps, _fieldSchema_xcomponentprops_service_params1, _fieldSchema_xcomponentprops_service1, _fieldSchema_xcomponentprops1;
        const filterFromSchema = isString(null == fieldSchema ? void 0 : null == (_fieldSchema_xcomponentprops = fieldSchema['x-component-props']) ? void 0 : null == (_fieldSchema_xcomponentprops_service = _fieldSchema_xcomponentprops.service) ? void 0 : null == (_fieldSchema_xcomponentprops_service_params = _fieldSchema_xcomponentprops_service.params) ? void 0 : _fieldSchema_xcomponentprops_service_params.filter) ? null == (_field_componentProps = field.componentProps) ? void 0 : null == (_field_componentProps_service = _field_componentProps.service) ? void 0 : null == (_field_componentProps_service_params = _field_componentProps_service.params) ? void 0 : _field_componentProps_service_params.filter : null == fieldSchema ? void 0 : null == (_fieldSchema_xcomponentprops1 = fieldSchema['x-component-props']) ? void 0 : null == (_fieldSchema_xcomponentprops_service1 = _fieldSchema_xcomponentprops1.service) ? void 0 : null == (_fieldSchema_xcomponentprops_service_params1 = _fieldSchema_xcomponentprops_service1.params) ? void 0 : _fieldSchema_xcomponentprops_service_params1.filter;
        const _run = async ()=>{
            var _service_params;
            const result = await parseFilter(mergeFilter([
                filterFromSchema || (null == service ? void 0 : null == (_service_params = service.params) ? void 0 : _service_params.filter)
            ]));
            setFieldServiceFilter(result);
        };
        const run = lodash.debounce(_run, DEBOUNCE_WAIT);
        _run();
        const dispose = reaction(()=>{
            const flat = flatten(filterFromSchema, {
                breakOn (param) {
                    let { key } = param;
                    return key.startsWith('$') && '$and' !== key && '$or' !== key;
                },
                transformValue (value) {
                    if (!isVariable(value)) return value;
                    const variableName = getVariableName(value);
                    const variable = findVariable(variableName);
                    const result = getValuesByPath({
                        [variableName]: (null == variable ? void 0 : variable.ctx) || {}
                    }, getPath(value));
                    return result;
                }
            });
            return flat;
        }, run);
        return dispose;
    }, [
        null == (_field_componentProps = field.componentProps) ? void 0 : null == (_field_componentProps_service = _field_componentProps.service) ? void 0 : null == (_field_componentProps_service_params = _field_componentProps_service.params) ? void 0 : _field_componentProps_service_params.filter,
        fieldSchema,
        findVariable,
        parseFilter,
        record,
        null == service ? void 0 : null == (_service_params = service.params) ? void 0 : _service_params.filter
    ]);
    const collectionField = useMemo(()=>getField(fieldSchema.name) || getCollectionJoinField(null == fieldSchema ? void 0 : fieldSchema['x-collection-field']), [
        fieldSchema
    ]);
    const sourceValue = null == record ? void 0 : record[null == collectionField ? void 0 : collectionField.sourceKey];
    const filter = useMemo(()=>{
        const isOToAny = [
            'oho',
            'o2m'
        ].includes(null == collectionField ? void 0 : collectionField.interface);
        return mergeFilter([
            mergeFilter([
                isOToAny && !isInFilterFormBlock(fieldSchema) && (null == collectionField ? void 0 : collectionField.foreignKey) && !useOriginalFilter ? {
                    [collectionField.foreignKey]: {
                        $is: null
                    }
                } : null,
                fieldServiceFilter
            ]),
            isOToAny && null != sourceValue && !isInFilterFormBlock(fieldSchema) && (null == collectionField ? void 0 : collectionField.foreignKey) && !useOriginalFilter ? {
                [collectionField.foreignKey]: {
                    $eq: sourceValue
                }
            } : null
        ], '$or');
    }, [
        null == collectionField ? void 0 : collectionField.interface,
        null == collectionField ? void 0 : collectionField.foreignKey,
        fieldSchema,
        fieldServiceFilter,
        sourceValue,
        useOriginalFilter
    ]);
    return useMemo(()=>({
            resource: null == collectionField ? void 0 : collectionField.target,
            action,
            ...service,
            params: {
                ...null == service ? void 0 : service.params,
                filter
            }
        }), [
        null == collectionField ? void 0 : collectionField.target,
        action,
        filter,
        service
    ]);
}
const useFieldNames = (props)=>{
    var _fieldSchema_xcomponentprops_field_uiSchema_xcomponentprops, _fieldSchema_xcomponentprops_field_uiSchema, _fieldSchema_xcomponentprops_field, _fieldSchema_xcomponentprops, _fieldSchema_xcomponentprops1;
    const fieldSchema = useFieldSchema();
    const fieldNames = (null == (_fieldSchema_xcomponentprops = fieldSchema['x-component-props']) ? void 0 : null == (_fieldSchema_xcomponentprops_field = _fieldSchema_xcomponentprops['field']) ? void 0 : null == (_fieldSchema_xcomponentprops_field_uiSchema = _fieldSchema_xcomponentprops_field['uiSchema']) ? void 0 : null == (_fieldSchema_xcomponentprops_field_uiSchema_xcomponentprops = _fieldSchema_xcomponentprops_field_uiSchema['x-component-props']) ? void 0 : _fieldSchema_xcomponentprops_field_uiSchema_xcomponentprops['fieldNames']) || (null == fieldSchema ? void 0 : null == (_fieldSchema_xcomponentprops1 = fieldSchema['x-component-props']) ? void 0 : _fieldSchema_xcomponentprops1['fieldNames']) || props.fieldNames;
    return {
        label: 'label',
        value: 'value',
        ...fieldNames
    };
};
const SubFormContext = createContext(null);
SubFormContext.displayName = 'SubFormContext';
const SubFormProvider = SubFormContext.Provider;
const useSubFormValue = ()=>{
    const { value, collection } = useContext(SubFormContext) || {};
    return {
        formValue: value,
        collection
    };
};
export { SubFormProvider, useServiceOptions as default, useAssociationFieldContext, useFieldNames, useInsertSchema, useSubFormValue };
