import {forwardRef, useEffect, useImperativeHandle, useMemo, useRef, useState} from "@wordpress/element";
import {__} from "@wordpress/i18n";
import {required, validate} from "../../../../../../../../validations";
import {getParameterNameValidator, getCallbackNameValidator} from "./_utils/validations";
import {closestCenter, DndContext, PointerSensor, useSensor, useSensors} from "@dnd-kit/core";
import {arrayMove, SortableContext, verticalListSortingStrategy} from "@dnd-kit/sortable";
import Input from "../../../../../../fields/input";
import BlockEditable from "../../../../../../fields/blockeditable";
import Description from "../../../../../../sections/description";
import NestedTabs from "../../../../../../sections/nested-tabs";
import SectionHeader from "../../../../../../sections/section-header";
import Empty from "../../../../containers/content/empty";
import AddParameter from "../../../../../../popups/actions/add-parameter";
import AddCallback from "../../../../../../popups/actions/add-callback";
import ParameterItem from "./_components/parameter-item";
import CallbackItem from "./_components/callback-item";
import {handleError} from "../../../../../../../helpers/notifications";
import {getTypeConfig} from "./_components/callback-item/types";
import useUnsavedChangesWarning from "../../../../../components/unsaved-changes-warning";
import {areDeepEqual} from "../../../../../../../../helpers";
import ContentBodyInner from "../../../../containers/content/body-inner";
import Container from "../../../../containers/content/container";
import ContentFooter from "../../../../containers/content/footer";

const PARAMETER_CONFIG_FIELDS = ['lead_capture_map_field'];

const AddEdit = forwardRef(({
                                data,
                                loading,
                                setLoading,
                                notifications,
                                activeTab,
                                setActiveTab,
                                onDeleteCallback,
                                saving,
                                onSave,
                                onDiscard,
                                navigate
                            }, ref) => {
    // Actions state
    const [isDataSet, setIsDataSet] = useState(false);
    const [actionCreated, setActionCreated] = useState(!!data?.id);
    const [showAddParameterPopup, setShowAddParameterPopup] = useState(false);
    const [showAddCallbackPopup, setShowAddCallbackPopup] = useState(false);
    const [newParameterIds, setNewParameterIds] = useState([]);
    const [deletedParameterIds, setDeletedParameterIds] = useState([]);
    const [newCallbackIds, setNewCallbackIds] = useState([]);

    // Data
    const [formData, setFormData] = useState({
        title: '',
        ai_instructions: '',
    });

    // Separate states for configuration
    const [parameters, setParameters] = useState([]);
    const [callbacks, setCallbacks] = useState([]);

    // State to track which items should be opened (for error display)
    const [openedParameterIds, setOpenedParameterIdsState] = useState(new Set());
    const [openedCallbackIds, setOpenedCallbackIdsState] = useState(new Set());

    // Refs to store validation trigger functions for parameters and callbacks
    const parameterValidationRefs = useRef(new Map());
    const callbackValidationRefs = useRef(new Map());

    // Unsaved changes tracking
    const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false);
    const initialFormData = useRef({
        title: '',
        ai_instructions: '',
    });
    const initialParameters = useRef([]);
    const initialCallbacks = useRef([]);

    // DnD context for parameters
    const sensors = useSensors(useSensor(PointerSensor));

    // Sort parameters by order for rendering
    const sortedParameters = useMemo(() => {
        return [...parameters].sort((a, b) => {
            // Handle missing order values - put them at the end
            const orderA = (a.order !== undefined && a.order !== null) ? a.order : Number.MAX_SAFE_INTEGER;
            const orderB = (b.order !== undefined && b.order !== null) ? b.order : Number.MAX_SAFE_INTEGER;
            return orderA - orderB;
        });
    }, [parameters]);

    const errors = {
        'title': useState(false),
        'ai_instructions': useState(false),
    };

    /**
     * Check if there are unsaved changes
     *
     * @return {boolean}
     */
    const checkUnsavedChanges = () => {
        // Compare form data
        const formDataEqual = areDeepEqual(formData, initialFormData.current);

        // Compare parameters - normalize by removing temporary IDs and comparing structure
        const normalizeForComparison = (item) => {
            const normalized = {...item};
            // Remove temporary string IDs for comparison (keep numeric IDs)
            if (typeof normalized.id === 'string') {
                delete normalized.id;
            }
            return normalized;
        };

        const normalizedParams = parameters.map(normalizeForComparison);
        const normalizedInitialParams = initialParameters.current.map(normalizeForComparison);
        const parametersEqual = areDeepEqual(normalizedParams, normalizedInitialParams);

        // Compare callbacks - same normalization
        const normalizedCallbacks = callbacks.map(normalizeForComparison);
        const normalizedInitialCallbacks = initialCallbacks.current.map(normalizeForComparison);
        const callbacksEqual = areDeepEqual(normalizedCallbacks, normalizedInitialCallbacks);

        return !formDataEqual || !parametersEqual || !callbacksEqual;
    };

    // Check for unsaved changes whenever data changes
    useEffect(() => {
        if (isDataSet) {
            const hasChanges = checkUnsavedChanges();
            setHasUnsavedChanges(hasChanges);
        }
    }, [formData, parameters, callbacks, isDataSet]);

    // Use unsaved changes warning hook for browser tab close/refresh
    useUnsavedChangesWarning(hasUnsavedChanges);

    /**
     * Reset initial data to current state (called after successful save)
     */
    const resetInitialData = () => {
        initialFormData.current = JSON.parse(JSON.stringify(formData));
        initialParameters.current = JSON.parse(JSON.stringify(parameters));
        initialCallbacks.current = JSON.parse(JSON.stringify(callbacks));
        setHasUnsavedChanges(false);
    };

    useImperativeHandle(ref, () => ({
        hasUnsavedChanges() {
            return hasUnsavedChanges;
        },
        resetInitialData() {
            resetInitialData();
        },
        getDataToSave() {
            // Validate based on active tab
            let hasError = false;
            let settings = {};

            if (activeTab === 'basic-info') {
                // Only validate basic info fields
                settings = {
                    'title': [formData.title],
                    'ai_instructions': [formData.ai_instructions],
                };
            } else {
                // Validate all fields for configuration tab
                settings = {
                    'title': [formData.title],
                    'ai_instructions': [formData.ai_instructions],
                };
            }

            for (const item of Object.keys(settings)) {
                if (!validateField(item, settings[item][0])) {
                    hasError = true;
                }
            }
            if (!hasError) {
                return LimbChatbot.Hooks.applyFilters('lbaic.admin.page.settings.knowledge.actions.dataToSave', formData, data?.id);
            }
            return false;
        },
        markAsCreated() {
            setActionCreated(true);
        },
        getNewParameters() {
            return parameters.filter(param => newParameterIds.includes(param.id));
        },
        getAllParameters() {
            return parameters;
        },
        getNewParameterIds() {
            return newParameterIds;
        },
        getDeletedParameterIds() {
            return deletedParameterIds;
        },
        updateParameterWithResponse(oldId, response) {
            setParameters(prevState => prevState.map(param => {
                if (param.id === oldId) {
                    // Preserve order from local parameter if server response doesn't have it
                    const order = response.order !== undefined && response.order !== null
                        ? response.order
                        : param.order;
                    return {...response, id: response.id, order};
                }
                return param;
            }));
            setNewParameterIds(prevState => prevState.filter(id => id !== oldId));
        },
        getNewCallbacks() {
            return callbacks.filter(callback => newCallbackIds.includes(callback.id));
        },
        getAllCallbacks() {
            return callbacks;
        },
        getNewCallbackIds() {
            return newCallbackIds;
        },
        updateCallbackWithResponse(oldId, response) {
            setCallbacks(prevState => prevState.map(callback => {
                if (callback.id === oldId) {
                    return {...response, id: response.id};
                }
                return callback;
            }));
            setNewCallbackIds(prevState => prevState.filter(id => id !== oldId));
        },
        validateAllParameters() {
            const errors = [];
            const sorted = [...parameters].sort((a, b) => {
                const orderA = a.order || 0;
                const orderB = b.order || 0;
                return orderA - orderB;
            });

            sorted.forEach((parameter, index) => {
                let hasError = false;

                // Trigger validation in the component if ref exists
                const validationTrigger = parameterValidationRefs.current.get(parameter.id);
                if (validationTrigger) {
                    validationTrigger();
                }

                // Always validate label (required)
                const labelValidation = validate(parameter.label || '', [required]);
                if (!labelValidation.valid) {
                    hasError = true;
                }

                // Always validate name using the same validator as the component
                let nameError = false;
                const nameValidator = getParameterNameValidator(
                    (error) => {
                        nameError = !!error;
                    },
                    parameter,
                    parameters,
                    callbacks
                );
                if (!nameValidator(parameter.name || '')) {
                    hasError = true;
                }

                // Validate vector_search specific field: cpt (required)
                if (parameter.type === 'vector_search') {
                    const cptValidation = validate(parameter.config?.cpt || '', [required]);
                    if (!cptValidation.valid) {
                        hasError = true;
                    }
                }

                if (hasError) {
                    errors.push({id: parameter.id, index});
                }
            });

            return errors;
        },
        validateAllCallbacks() {
            const errors = [];

            callbacks.forEach((callback, index) => {
                let hasError = false;

                // Trigger validation in the component if ref exists
                const validationTrigger = callbackValidationRefs.current.get(callback.id);
                if (validationTrigger) {
                    validationTrigger();
                }

                // Always validate name (required, unique, slug format)
                let nameError = false;
                const nameValidator = getCallbackNameValidator(
                    (error) => {
                        nameError = !!error;
                    },
                    callback,
                    parameters,
                    callbacks
                );
                if (!nameValidator(callback.name || '')) {
                    hasError = true;
                }

                // Validate type-specific required fields
                if (callback.type === 'email') {
                    // Email requires: to, subject, body_text
                    const toValidation = validate(callback.config?.to || '', [required]);
                    if (!toValidation.valid) {
                        hasError = true;
                    }
                    const subjectValidation = validate(callback.config?.subject || '', [required]);
                    if (!subjectValidation.valid) {
                        hasError = true;
                    }
                    const bodyTextValidation = validate(callback.config?.body_text || '', [required]);
                    if (!bodyTextValidation.valid) {
                        hasError = true;
                    }
                } else if (callback.type === 'slack') {
                    // Slack requires: title, config_id, content
                    const titleValidation = validate(callback.title || '', [required]);
                    if (!titleValidation.valid) {
                        hasError = true;
                    }
                    const configIdValidation = validate(callback.config?.config_id || '', [required]);
                    if (!configIdValidation.valid) {
                        hasError = true;
                    }
                    const contentValidation = validate(callback.config?.content || '', [required]);
                    if (!contentValidation.valid) {
                        hasError = true;
                    }
                }
                // Note: Unknown callback types will only validate the name field (already validated above)

                if (hasError) {
                    errors.push({id: callback.id, index});
                }
            });

            return errors;
        },
        setOpenedParameterIds(ids) {
            // Clear first to ensure transition, then set new values
            setOpenedParameterIdsState(new Set());
            // Use setTimeout to ensure state update happens before setting new values
            setTimeout(() => {
                setOpenedParameterIdsState(ids);
            }, 0);
        },
        setOpenedCallbackIds(ids) {
            // Clear first to ensure transition, then set new values
            setOpenedCallbackIdsState(new Set());
            // Use setTimeout to ensure state update happens before setting new values
            setTimeout(() => {
                setOpenedCallbackIdsState(ids);
            }, 0);
        }
    }));

    useEffect(() => {
        setDefaultValues();
    }, []);

    /**
     * Validate field
     *
     * @param {string} name Field name
     * @param {any} value Field value
     * @return {boolean}
     */
    const validateField = (name, value) => {
        try {
            let validations = [];

            switch (name) {
                case 'title':
                    validations = [required];
                    break;
                case 'ai_instructions':
                    validations = [required];
                    break;
                default:
                    break;
            }
            const res = validate(value, validations);
            // Update field errors state
            errors[name][1](!res.valid ? res.message : false);

            return res.valid;
        } catch (e) {
            handleError(e, notifications.set, {
                title: __("Field validation failed.", 'limb-chatbot'),
                description: e.message ? __(e.message, 'limb-chatbot') : __("Something went wrong.", 'limb-chatbot'),
            });
            return false;
        }
    }

    const setDefaultValues = async () => {
        setLoading(prev => prev + 1);

        // Title
        const title = data?.title || '';
        // AI instructions
        const aiInstructions = data?.ai_instructions || '';
        // Parameters - handle both array and object with items
        let parametersData = [];
        if (data?.parameters) {
            let parametersArray = [];
            if (Array.isArray(data.parameters)) {
                parametersArray = data.parameters;
            } else if (Array.isArray(data.parameters.items)) {
                parametersArray = data.parameters.items;
            }
            parametersData = parametersArray.map((param, index) => ({
                ...param,
                // Ensure config exists and is an object
                config: param.config && typeof param.config === 'object' ? param.config : {},
                // Set order to existing value or index + 1 if not set
                order: param.order !== undefined && param.order !== null ? param.order : (index + 1)
            }));
        }
        // Callbacks - handle both array and object with items, check both callbacks and action_callbacks
        let callbacksData = [];
        const callbacksSource = data?.callbacks || data?.action_callbacks;
        if (callbacksSource) {
            if (Array.isArray(callbacksSource)) {
                callbacksData = callbacksSource;
            } else if (callbacksSource.items && Array.isArray(callbacksSource.items)) {
                callbacksData = callbacksSource.items;
            }
        }

        // Map API callback data to component format (status -> enabled)
        // Keep all fields from API including config structure
        callbacksData = callbacksData.map((callback, index) => {
            const config = callback.config || {};

            // Keep config as is
            let processedConfig = {...config};

            return {
                ...callback,
                enabled: callback.status === 1,
                // Set order to index + 1 if not already set
                order: callback.order !== undefined && callback.order !== null ? callback.order : (index + 1),
                // Preserve config structure with processed headers
                config: processedConfig
            };
        });

        // Setup default values
        setFormData(prevState => ({
            ...prevState,
            title: title,
            ai_instructions: aiInstructions,
        }));

        // Set configuration data
        setParameters(parametersData);
        setCallbacks(callbacksData);
        // Reset deleted parameter IDs when loading new data
        setDeletedParameterIds([]);

        // Store initial data for comparison
        initialFormData.current = {
            title: title,
            ai_instructions: aiInstructions,
        };
        initialParameters.current = JSON.parse(JSON.stringify(parametersData));
        initialCallbacks.current = JSON.parse(JSON.stringify(callbacksData));

        setIsDataSet(true);
        setLoading(prev => prev - 1);
    }

    /**
     * Open add parameter popup
     */
    const addParameter = () => {
        setShowAddParameterPopup(true);
    };

    /**
     * Handle parameter type selection
     *
     * @param {string} type Parameter type
     */
    const handleParameterTypeSelect = (type) => {
        const id = Math.random().toString(36).substring(2, 12);
        setParameters(prevState => {
            // Calculate new order based on max existing order value
            const maxOrder = prevState.length > 0
                ? Math.max(...prevState.map(p => p.order || 0))
                : 0;
            const newOrder = maxOrder + 1;
            return [
                ...prevState,
                {
                    id,
                    name: '',
                    label: '',
                    type: type,
                    required: false,
                    placeholder: '',
                    question: '',
                    order: newOrder,
                }
            ];
        });
        setNewParameterIds(prevState => [...prevState, id]);
        setShowAddParameterPopup(false);
    };

    /**
     * Update parameter field
     *
     * @param {number} index Parameter index (from sorted array)
     * @param {string} field Field name
     * @param {any} value Field value
     */
    const updateParameter = (index, field, value) => {
        setParameters(prevState => {
            const sorted = [...prevState].sort((a, b) => {
                const orderA = a.order || 0;
                const orderB = b.order || 0;
                return orderA - orderB;
            });
            const parameter = sorted[index];
            if (!parameter) return prevState;

            return prevState.map(item => {
                if (item.id === parameter.id) {
                    // Handle config fields
                    if (PARAMETER_CONFIG_FIELDS.includes(field)) {
                        return {
                            ...item,
                            config: {
                                ...(item.config || {}),
                                [field]: value
                            }
                        };
                    }
                    return {...item, [field]: value};
                }
                return item;
            });
        });
    };

    /**
     * Remove parameter
     *
     * @param {number} index Parameter index (from sorted array)
     */
    const removeParameter = (index) => {
        setParameters(prevState => {
            const sorted = [...prevState].sort((a, b) => {
                const orderA = a.order || 0;
                const orderB = b.order || 0;
                return orderA - orderB;
            });
            const parameter = sorted[index];
            if (!parameter) return prevState;

            // If parameter has a numeric ID (from server), track it for deletion
            if (parameter?.id && typeof parameter.id === 'number') {
                setDeletedParameterIds(prevState => [...prevState, parameter.id]);
            }
            // Remove from newParameterIds if it was a new parameter
            if (parameter?.id && newParameterIds.includes(parameter.id)) {
                setNewParameterIds(prevState => prevState.filter(id => id !== parameter.id));
            }

            const filtered = prevState.filter(item => item.id !== parameter.id);
            // Update order values after removal
            return filtered.map((item, i) => ({
                ...item,
                order: i + 1
            }));
        });
    };

    /**
     * Move parameter up
     *
     * @param {number} index Parameter index (from sorted array)
     */
    const moveParameterUp = (index) => {
        if (index !== 0) {
            setParameters(prevState => {
                const sorted = [...prevState].sort((a, b) => {
                    const orderA = a.order || 0;
                    const orderB = b.order || 0;
                    return orderA - orderB;
                });
                const moved = arrayMove(sorted, index, index - 1);
                // Update order values based on new positions
                const withNewOrders = moved.map((item, i) => ({
                    ...item,
                    order: i + 1
                }));
                // Map back to original array structure
                return prevState.map(item => {
                    const updated = withNewOrders.find(p => p.id === item.id);
                    return updated || item;
                });
            });
        }
    };

    /**
     * Move parameter down
     *
     * @param {number} index Parameter index (from sorted array)
     */
    const moveParameterDown = (index) => {
        setParameters(prevState => {
            const sorted = [...prevState].sort((a, b) => {
                const orderA = a.order || 0;
                const orderB = b.order || 0;
                return orderA - orderB;
            });
            if (index !== sorted.length - 1) {
                const moved = arrayMove(sorted, index, index + 1);
                // Update order values based on new positions
                const withNewOrders = moved.map((item, i) => ({
                    ...item,
                    order: i + 1
                }));
                // Map back to original array structure
                return prevState.map(item => {
                    const updated = withNewOrders.find(p => p.id === item.id);
                    return updated || item;
                });
            }
            return prevState;
        });
    };

    /**
     * Handle DnD end for parameters
     *
     * @param event
     */
    const handleParameterDragEnd = (event) => {
        const {active, over} = event;

        if (active.id !== over.id) {
            setParameters(prevState => {
                // Sort first to get correct indices
                const sorted = [...prevState].sort((a, b) => {
                    const orderA = a.order || 0;
                    const orderB = b.order || 0;
                    return orderA - orderB;
                });

                const oldIndex = sorted.findIndex(item => item.id === active.id);
                const newIndex = sorted.findIndex(item => item.id === over.id);

                if (oldIndex === -1 || newIndex === -1) return prevState;

                const moved = arrayMove(sorted, oldIndex, newIndex);
                // Update order values based on new positions
                const withNewOrders = moved.map((item, index) => ({
                    ...item,
                    order: index + 1
                }));

                // Map back to original array structure
                return prevState.map(item => {
                    const updated = withNewOrders.find(p => p.id === item.id);
                    return updated || item;
                });
            });
        }
    };

    /**
     * Open add callback popup
     */
    const addCallback = () => {
        setShowAddCallbackPopup(true);
    };

    /**
     * Handle callback type selection
     *
     * @param {string} type Callback type
     */
    const handleCallbackTypeSelect = (type) => {
        const id = Math.random().toString(36).substring(2, 12);
        const typeConfig = getTypeConfig(type);
        const defaultValues = typeof typeConfig?.defaultValues === 'function'
            ? typeConfig.defaultValues()
            : (typeConfig?.defaultValues || {});

        setCallbacks(prevState => {
            const newOrder = prevState.length + 1;
            const newCallback = {
                id,
                type,
                enabled: true,
                order: newOrder,
                ...defaultValues,
            };

            if (typeof newCallback.name === 'undefined' || newCallback.name === null) {
                newCallback.name = '';
            }

            return [...prevState, newCallback];
        });
        setNewCallbackIds(prevState => [...prevState, id]);
        setShowAddCallbackPopup(false);
    };

    /**
     * Update callback field
     *
     * @param {number} index Callback index
     * @param {string} field Field name
     * @param {any} value Field value
     */
    const updateCallback = (index, field, value) => {
        setCallbacks(prevState => prevState.map((item, i) => {
            if (i === index) {
                // Fields that should be in config for email type
                const emailConfigFields = ['to', 'subject', 'body_text', 'reply_to'];
                // Fields that should be in config for slack type
                const slackConfigFields = ['config_id', 'channel', 'content'];
                // Fields that should be in config for all callback types
                const commonConfigFields = ['success_message', 'show_collected_data'];

                // Check if this is a config field
                if (emailConfigFields.includes(field) || slackConfigFields.includes(field) || commonConfigFields.includes(field)) {
                    return {
                        ...item,
                        config: {
                            ...(item.config || {}),
                            [field]: value
                        }
                    };
                }

                // For other fields, update at top level
                return {...item, [field]: value};
            }
            return item;
        }));
    };

    /**
     * Remove callback
     *
     * @param {number} index Callback index
     */
    const removeCallback = (index) => {
        setCallbacks(prevState => {
            const filtered = prevState.filter((item, i) => i !== index);
            // Update order numbers after removal
            return filtered.map((item, i) => ({
                ...item,
                order: i + 1
            }));
        });
    };

    // Tabs configuration with dynamic disabled state
    const tabs = [
        {
            label: __("Basic info", 'limb-chatbot'),
            slug: 'basic-info',
        },
        {
            label: __("Configuration", 'limb-chatbot'),
            slug: 'configuration',
            disabled: !actionCreated,
        },
    ];

    return <>
        <ContentBodyInner>
            <Container className="lbaic-settings-a-es">
                <NestedTabs
                    tabs={tabs}
                    activeTab={activeTab}
                    onTabChange={setActiveTab}
                    className="lbaic-settings-divider-no-pi"
                />
                {activeTab === 'basic-info' && (
                    <>
                        <div className='lbaic-settings-column'>
                            <div className='lbaic-settings-column-in'>
                                <Input value={formData.title}
                                       setValue={(value) => setFormData(prevState => ({
                                           ...prevState,
                                           title: value
                                       }))}
                                       placeholder={__("Title", 'limb-chatbot')}
                                       autofocus
                                       validate={(value) => validateField('title', value)}
                                       errorMessage={errors['title'][0]}/>
                                <Description>
                                    {__("This is the internal identifier for this action.", 'limb-chatbot')}
                                </Description>
                            </div>
                            <div className='lbaic-settings-column-in'/>
                        </div>
                        <div className='lbaic-settings-column'>
                            <div className='lbaic-settings-column-in'>
                                <BlockEditable
                                    value={formData.ai_instructions}
                                    setValue={(value) => setFormData(prevState => ({
                                        ...prevState,
                                        ai_instructions: value
                                    }))}
                                    label={__("When to use", 'limb-chatbot')}
                                    validate={(value) => validateField('ai_instructions', value)}
                                    errorMessage={errors['ai_instructions'][0]}
                                    notifications={notifications}
                                    opened={false}
                                />
                                <Description>
                                    {__("Guide the AI on when and how to trigger this action during conversations.", 'limb-chatbot')}
                                </Description>
                            </div>
                        </div>
                    </>
                )}
                {activeTab === 'configuration' && (
                    <>
                        <div className='lbaic-settings-column'>
                            {/* Parameters section */}
                            <div className='lbaic-settings-column-in'>
                                {!sortedParameters?.length &&
                                    <Empty
                                        className='sm'
                                        title={__("What to collect?", 'limb-chatbot')}
                                        titleClassName="lbaic-settings-cb-pw-empty-title"
                                        subtitle={__("This action doesn't require user input. Add parameters if you need to collect data from users.", 'limb-chatbot')}
                                        subtitleClassName="lbaic-settings-cb-pw-empty-subtitle"
                                        icon={false}
                                    >
                                        <div className='lbaic-settings-empty-actions'>
                                            <button
                                                className='lbaic-settings-cb-pw-table-actions-item lbaic-settings-button lbaic-settings-button-center lbaic-settings-button-h-40 lbaic-settings-button-primary'
                                                onClick={addParameter}>
                                            <span
                                                className='lbaic-settings-button-label'>{__("+ Add parameter", 'limb-chatbot')}</span>
                                            </button>
                                        </div>
                                    </Empty>}
                                {sortedParameters?.length > 0 &&
                                    <>
                                        <SectionHeader
                                            title={__("What to collect?", 'limb-chatbot')}
                                            description={__("Data to collect from users in the chat before executing this action", 'limb-chatbot')}
                                            onButtonClick={addParameter}
                                            buttonLabel={__("+ Add parameter", 'limb-chatbot')}
                                            badgeLabel={sortedParameters.length}
                                        />
                                        <div
                                            className='lbaic-settings-table-accordion lbaic-settings-cb-pw-table-inside'>
                                            <DndContext sensors={sensors} collisionDetection={closestCenter}
                                                        onDragEnd={handleParameterDragEnd}>
                                                <SortableContext items={sortedParameters}
                                                                 strategy={verticalListSortingStrategy}>
                                                    {sortedParameters.map((item, i) => (
                                                        <ParameterItem
                                                            key={item.id}
                                                            parameter={item}
                                                            index={i}
                                                            moveUp={() => moveParameterUp(i)}
                                                            moveDown={() => moveParameterDown(i)}
                                                            update={updateParameter}
                                                            remove={removeParameter}
                                                            newParameterIds={newParameterIds}
                                                            notifications={notifications}
                                                            allParameters={parameters}
                                                            allCallbacks={callbacks}
                                                            forceOpen={openedParameterIds.has(item.id)}
                                                            onValidationRef={(ref) => {
                                                                if (ref) {
                                                                    parameterValidationRefs.current.set(item.id, ref);
                                                                } else {
                                                                    parameterValidationRefs.current.delete(item.id);
                                                                }
                                                            }}
                                                            setLoading={setLoading}
                                                            navigate={navigate}
                                                            onSave={onSave}
                                                        />
                                                    ))}
                                                </SortableContext>
                                            </DndContext>
                                        </div>
                                    </>}
                            </div>
                        </div>
                        <div className='lbaic-settings-column'>
                            {/* Callbacks section */}
                            <div className='lbaic-settings-column-in'>
                                {!callbacks?.length &&
                                    <Empty
                                        className='sm'
                                        title={__("What to do?", 'limb-chatbot')}
                                        titleClassName="lbaic-settings-cb-pw-empty-title"
                                        subtitle={__("Action to perform with the collected data", 'limb-chatbot')}
                                        subtitleClassName="lbaic-settings-cb-pw-empty-subtitle"
                                        icon={false}
                                    >
                                        <div className='lbaic-settings-empty-actions'>
                                            <button
                                                className='lbaic-settings-cb-pw-table-actions-item lbaic-settings-button lbaic-settings-button-center lbaic-settings-button-h-40 lbaic-settings-button-primary'
                                                onClick={addCallback}>
                                            <span
                                                className='lbaic-settings-button-label'>{__("+ Add handler", 'limb-chatbot')}</span>
                                            </button>
                                        </div>
                                    </Empty>}
                                {callbacks?.length > 0 &&
                                    <>
                                        <SectionHeader
                                            title={__("What to do?", 'limb-chatbot')}
                                            description={__("Handler can use data from parameters.", 'limb-chatbot')}
                                        />
                                        <div className='lbaic-settings-table-accordion'>
                                            {callbacks.map((item, i) =>
                                                <CallbackItem key={item.id} callback={item} index={i}
                                                              update={updateCallback}
                                                              remove={removeCallback}
                                                              newCallbackIds={newCallbackIds}
                                                              notifications={notifications}
                                                              actionId={data?.id}
                                                              onDeleteCallback={onDeleteCallback}
                                                              allParameters={parameters}
                                                              allCallbacks={callbacks}
                                                              forceOpen={openedCallbackIds.has(item.id)}
                                                              onValidationRef={(ref) => {
                                                                  if (ref) {
                                                                      callbackValidationRefs.current.set(item.id, ref);
                                                                  } else {
                                                                      callbackValidationRefs.current.delete(item.id);
                                                                  }
                                                              }}/>)}
                                        </div>
                                    </>}
                            </div>
                        </div>
                    </>
                )}
                {showAddParameterPopup &&
                    <AddParameter
                        close={() => setShowAddParameterPopup(false)}
                        onSelect={handleParameterTypeSelect}
                    />}
                {showAddCallbackPopup &&
                    <AddCallback
                        close={() => setShowAddCallbackPopup(false)}
                        onSelect={handleCallbackTypeSelect}
                    />}
            </Container>
        </ContentBodyInner>
        <ContentFooter
            save={onSave}
            discard={onDiscard}
            loading={loading}
            saving={saving}
            hasUnsavedChanges={hasUnsavedChanges}
            disableDiscardButton={false}
            saveLabel={activeTab === 'basic-info' && !data?.id ? __("Config →", 'limb-chatbot') : __("Save", 'limb-chatbot')}
            discardLabel={__("Cancel", 'limb-chatbot')}
        />
    </>
});

export default AddEdit;