import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { interpolate, translate, useLanguage } from '@stack-spot/portal-translate';
import { Fragment, useMemo } from 'react';
import { useJinjaContext } from '../context/JinjaContext.js';
import { JinjaExpressionVariable } from '../context/JinjaVariable.js';
import { useComputedInputsEffect, useIsRepeating } from '../form/hooks.js';
import { JinjaForm } from '../form/JinjaForm.js';
import { JinjaFormModel } from '../form/JinjaFormModel.js';
import { debouncePromise } from '../utils/promise.js';
import { BooleanField } from './components/BooleanField.js';
import { IntField } from './components/IntField.js';
import { ListField } from './components/ListField.js';
import { MultiselectField } from './components/MultiselectField.js';
import { PasswordField } from './components/Password.js';
import { RequiredConnectionField } from './components/RequiredConnectionField.js';
import { SelectField } from './components/SelectField.js';
import { TextField } from './components/TextField.js';
import { VariableField } from './components/VariableField.js';
import { useConnectionInterfaceConfig, useGeneratedConnectionsManager } from './ConnectionInterface.js';
import { errorDictionary } from './error-dictionary.js';
import './style.css';
import { validateGeneratedConnection } from './validate-generated-connection.js';
import { globalVariablesContextName, PluginVariablesContext } from './VariablesContext.js';
const components = {
    bool: BooleanField,
    int: IntField,
    multiselect: MultiselectField,
    list: ListField,
    'required-connection': RequiredConnectionField,
    password: PasswordField,
    select: SelectField,
    text: VariableField,
    'generated-connection': TextField,
};
function getDefaultAndDisabled(inputEnv, def, valuesByEnv = []) {
    if (!inputEnv || valuesByEnv.length === 1) {
        return {
            default: valuesByEnv[0]?.value ?? def,
            disabled: valuesByEnv[0]?.mandate,
        };
    }
    if (!valuesByEnv.length) {
        return { default: def, disabled: false };
    }
    const byEnvMap = {};
    const disabled = {};
    for (const env of valuesByEnv) {
        byEnvMap[env.envName] = env.value;
        disabled[env.envName] = !!env.mandate;
    }
    return { default: byEnvMap, disabled };
}
function getDefaultValueByType(type) {
    switch (type) {
        case 'list': return [];
        case 'multiselect': return [];
        case 'object': return {};
        case 'bool': return true;
        default: return undefined;
    }
}
function inputToFieldConfig(
// eslint-disable-next-line @typescript-eslint/no-unused-vars
input, envs, language, formName, connectionInterfacesConfig, generatedConnectionsManager) {
    const { type, name, required, default: defaultValue, condition, help, pattern, inputEnv = false, inputs, isGlobal, valuesByEnv, ...props } = input;
    const label = required ? `${props.label} *` : props.label;
    const startRepeating = (valuesByEnv?.length ?? 0) > 1;
    const def = defaultValue ?? getDefaultValueByType(type);
    if (type === 'object') {
        return {
            name,
            label,
            shouldRender: condition,
            children: inputs?.map(i => inputToFieldConfig({
                ...i, valuesByEnv: startRepeating ? [] : valuesByEnv?.map(byEnv => ({ ...byEnv, value: byEnv.value?.[i.name] })),
            }, envs, language, formName, connectionInterfacesConfig, generatedConnectionsManager)) ?? [],
            repeat: inputEnv ? envs : undefined,
            startRepeating,
            ascend: isGlobal ? globalVariablesContextName : undefined,
            props,
            metadata: input,
            controlled: false,
            ...getDefaultAndDisabled(inputEnv, def, valuesByEnv),
        };
    }
    const isConnectionInterfaceNameAvailable = debouncePromise(connectionInterfacesConfig.isConnectionInterfaceNameAvailable, 500);
    const v = {
        jinja: type === 'text' ? { mode: 'replace-variable' } : false,
        name,
        label,
        component: components[type] ?? Fragment,
        required: required ?? true,
        shouldRender: condition,
        repeat: inputEnv ? envs : undefined,
        startRepeating,
        ascend: isGlobal ? globalVariablesContextName : undefined,
        help,
        // @ts-ignore
        model: input.input
            ? inputToFieldConfig(input.input, envs, language, formName, connectionInterfacesConfig, generatedConnectionsManager)
            : undefined,
        metadata: input,
        controlled: type != 'list' || input.input?.type != 'object',
        validation: async (value) => {
            const patternError = pattern
                ? `${value}`.match(`^${pattern}$`) ? undefined : interpolate(translate(errorDictionary, language).pattern, pattern)
                : undefined;
            const connectionNameError = await validateGeneratedConnection(value, input, language, formName, isConnectionInterfaceNameAvailable, generatedConnectionsManager);
            if (type === 'int') {
                const parsed = parseInt(value);
                if (parsed > Number.MAX_SAFE_INTEGER || parsed < Number.MIN_SAFE_INTEGER) {
                    return translate(errorDictionary, language).numberOutOfBounds;
                }
            }
            return patternError || connectionNameError;
        },
        props,
        ...getDefaultAndDisabled(inputEnv, def, valuesByEnv),
    };
    return v;
}
export const FieldRenderer = ({ Component, input }) => {
    const isRepeating = useIsRepeating(Component.variable);
    const children = isRepeating ? Component.repeat : Component.fields;
    return (_jsx("div", { className: "dynamic-field", "data-field-type": input.type.toLowerCase(), children: children
            ? (_jsx(Component, { children: children.map((c, i) => _jsx(FieldRenderer, { Component: c, input: isRepeating ? input : input.inputs[i] }, `${c.name}-${i}`)) })) : _jsx(Component, {}) }));
};
const Form = ({ inputs, computedInputs, globalComputedInputs, name, onSubmit, envs, children, formModelRef, ...props }) => {
    const parent = useJinjaContext();
    const language = useLanguage();
    const connectionInterfacesConfig = useConnectionInterfaceConfig();
    const generatedConnectionsManager = useGeneratedConnectionsManager();
    const formModel = useMemo(() => new JinjaFormModel({
        fields: inputs.map(i => inputToFieldConfig(i, envs, language, name, connectionInterfacesConfig, generatedConnectionsManager)),
        computed: computedInputs?.reduce((result, value) => {
            result[value.name] = value.expression;
            return result;
        }, {}),
        name,
        onSubmit,
        parent,
    }), [inputs, parent]);
    if (formModelRef) {
        formModelRef.current = formModel;
    }
    const globalComputedVariables = useMemo(() => {
        const ctx = parent?.closest(globalVariablesContextName);
        const vars = globalComputedInputs?.map((g) => new JinjaExpressionVariable(g.name, g.expression));
        if (ctx && vars)
            ctx.addVariables(vars);
        return vars;
    }, [globalComputedInputs, parent]);
    useComputedInputsEffect(globalComputedVariables, formModel.context);
    return (_jsxs(JinjaForm, { ...props, model: formModel, className: "dynamic-form", children: [formModel.fields.map((f, i) => _jsx(FieldRenderer, { Component: f, input: inputs[i] }, `${f.name}-${i}`)), children] }));
};
export const DynamicForm = ({ pluginVariables = [], ...props }) => (_jsx(PluginVariablesContext, { variables: pluginVariables, children: _jsx(Form, { ...props }) }));
//# sourceMappingURL=index.js.map