import {useEffect, useRef, useState} from "@wordpress/element";
import {__, sprintf} from "@wordpress/i18n";
import Container from "../../../containers/content/container";
import Empty from "../../../containers/content/empty";
import ContentLoading from "../../../containers/content/loading";
import AddEdit from "./add-edit";
import Table from "../../../../../sections/table";
import ToggleButton from "../../../../../fields/toggle-button";
import Tooltip from "../../../../../fields/tooltip";
import TabSettings from "../../../../components/tab-settings";
import {CreateAction, UpdateAction, GetActions, GetAction, DeleteAction} from "../../../../../../rest/actions";
import {
    CreateActionParameter,
    UpdateActionParameter,
    DeleteActionParameter
} from "../../../../../../rest/action-parameters";
import {
    CreateActionCallback,
    UpdateActionCallback,
    DeleteActionCallback
} from "../../../../../../rest/action-callbacks";
import {handleSuccess, handleError, handleWarning} from "../../../../../../helpers/notifications";
import confirm from "../../../../../../helpers/confirm";
import {handlePaginationAfterDeletion, getInitialData} from "../../../../../../helpers";
import {UpdateSetting} from "../../../../../../rest/settings";
import Entries from "./entries";

// Constants
const TAB_NAME = 'settings.chatbot.actions';

export default function KnowledgeActions({notifications, navigate, updatePositions, children}) {
    // Actions states
    const [loading, setLoading] = useState(0);
    const [saving, setSaving] = useState(false);
    const [deleting, setDeleting] = useState(false);
    const [addingEditingAction, setAddingEditingAction] = useState(false);
    const [showEntries, setShowEntries] = useState(false);
    const [selectedAction, setSelectedAction] = useState(null);
    const [activeTab, setActiveTab] = useState('basic-info');
    const [actions, setActions] = useState([]);
    const [isDataFetched, setIsDataFetched] = useState(false);
    const [actionsPagination, setActionsPagination] = useState({
        page: 1,
        perPage: LimbChatbot.screen_options?.lbaic_items_per_page || 10,
        total: 0,
    });
    const [actionsOrder, setActionsOrder] = useState({
        orderBy: 'created_at',
        order: 'desc',
    });
    const wasJustCreated = useRef(false);

    // Settings for TabSettings (action_ids is a chatbot setting)
    const settings = {
        'action_ids': useState([]),
    };
    const [listSaving, setListSaving] = useState(false);

    // Initial data ref for TabSettings - managed by this component
    const initialDataRef = useRef(getInitialData(settings));

    // Ref for add/edit form
    const addEditActionRef = useRef(null);
    // Track unsaved changes state for AddEdit mode
    const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false);

    /**
     * Map parameter data to API format
     *
     * @param {object} parameter Parameter data from form
     * @return {object} Mapped parameter data for API
     */
    const mapParameterToApiFormat = (parameter) => {
        const apiData = {
            name: parameter.name,
            label: parameter.label,
            type: parameter.type,
            required: parameter.required ? 1 : 0,
        };

        // Order field (required for proper sequencing)
        if (typeof parameter.order === 'number' && parameter.order >= 0) {
            apiData.order = parameter.order;
        }

        // Optional fields
        if (parameter.question) {
            apiData.question = parameter.question;
        }
        if (parameter.default_value !== undefined && parameter.default_value !== null && parameter.default_value !== '') {
            apiData.default_value = parameter.default_value;
        }
        if (parameter.placeholder) {
            apiData.placeholder = parameter.placeholder;
        }

        // Config
        apiData.config = parameter.config || {};

        // Validation rules
        if (parameter.validation_rules && Object.keys(parameter.validation_rules).length > 0) {
            apiData.validation_rules = parameter.validation_rules;
        }

        // Suggestions
        if (parameter.suggestions && parameter.suggestions.length > 0) {
            apiData.suggestions = parameter.suggestions;
        }

        return apiData;
    };

    /**
     * Map callback data to API format
     *
     * @param {object} callback Callback data from form
     * @return {object} Mapped callback data for API
     */
    const mapCallbackToApiFormat = (callback) => {
        const apiData = {
            name: callback.name || '',
            type: callback.type,
            status: callback.enabled ? 1 : 0,
        };

        // Optional fields
        if (callback.title) {
            apiData.title = callback.title;
        }
        if (callback.description) {
            apiData.description = callback.description;
        }
        if (callback.order !== undefined && callback.order !== null) {
            apiData.order = callback.order;
        }
        // Always include is_required (even if 0 or false)
        if (callback.is_required !== undefined && callback.is_required !== null) {
            apiData.is_required = callback.is_required ? 1 : 0;
        } else {
            // Default to 0 if not set
            apiData.is_required = 0;
        }

        // Config - ensure config object exists if present
        if (callback.config) {
            apiData.config = {...(callback.config || {})};
        }

        return apiData;
    };

    /**
     * Save parameters for an action (both new and updated)
     *
     * @param {number} actionId Action ID
     * @return {Promise<void>}
     */
    const saveNewParameters = async (actionId) => {
        const allParameters = addEditActionRef.current?.getAllParameters() || [];
        const newParameterIds = addEditActionRef.current?.getNewParameterIds() || [];
        const newParameters = allParameters.filter(param => newParameterIds.includes(param.id));
        const existingParameters = allParameters.filter(param =>
            param.id &&
            typeof param.id === 'number' &&
            !newParameterIds.includes(param.id)
        );

        const errors = [];

        // Save new parameters
        for (const parameter of newParameters) {
            try {
                const apiData = mapParameterToApiFormat(parameter);
                const response = await CreateActionParameter(
                    LimbChatbot.rest.url,
                    LimbChatbot.rest.nonce,
                    actionId,
                    apiData
                );

                if (response?.id) {
                    // Update the parameter with the response
                    if (addEditActionRef.current?.updateParameterWithResponse) {
                        addEditActionRef.current.updateParameterWithResponse(parameter.id, response);
                    }
                } else {
                    errors.push({
                        type: 'create',
                        parameter: parameter,
                        error: new Error(__("Failed to create parameter. Invalid response.", 'limb-chatbot'))
                    });
                }
            } catch (e) {
                errors.push({
                    type: 'create',
                    parameter: parameter,
                    error: e
                });
            }
        }

        // Update existing parameters
        for (const parameter of existingParameters) {
            try {
                const apiData = mapParameterToApiFormat(parameter);
                const response = await UpdateActionParameter(
                    LimbChatbot.rest.url,
                    LimbChatbot.rest.nonce,
                    actionId,
                    parameter.id,
                    apiData
                );

                if (!response?.id) {
                    errors.push({
                        type: 'update',
                        parameter: parameter,
                        error: new Error(__("Failed to update parameter. Invalid response.", 'limb-chatbot'))
                    });
                }
            } catch (e) {
                errors.push({
                    type: 'update',
                    parameter: parameter,
                    error: e
                });
            }
        }

        // Delete removed parameters
        const deletedParameterIds = addEditActionRef.current?.getDeletedParameterIds() || [];
        for (const parameterId of deletedParameterIds) {
            try {
                await DeleteActionParameter(
                    LimbChatbot.rest.url,
                    LimbChatbot.rest.nonce,
                    actionId,
                    parameterId
                );
            } catch (e) {
                errors.push({
                    type: 'delete',
                    parameter: {id: parameterId},
                    error: e
                });
            }
        }

        // Show errors if any occurred
        if (errors.length > 0) {
            const errorMessages = errors.map(err => {
                const parameterName = err.parameter?.name || err.parameter?.label || __("Unknown parameter", 'limb-chatbot');
                const action = err.type === 'create' ? __("create", 'limb-chatbot') : err.type === 'update' ? __("update", 'limb-chatbot') : __("delete", 'limb-chatbot');
                return `${parameterName}: ${err.error.message || __("Failed to", 'limb-chatbot')} ${action}`;
            }).join('<br/>');

            handleError(new Error(errorMessages), notifications.set, {
                title: __("Some parameters failed to save.", 'limb-chatbot'),
                description: errorMessages,
            });
        }
    };

    /**
     * Save callbacks for an action (both new and updated)
     *
     * @param {number} actionId Action ID
     * @return {Promise<void>}
     */
    const saveCallbacks = async (actionId) => {
        const allCallbacks = addEditActionRef.current?.getAllCallbacks() || [];
        const newCallbackIds = addEditActionRef.current?.getNewCallbackIds() || [];
        const newCallbacks = allCallbacks.filter(callback => newCallbackIds.includes(callback.id));
        const existingCallbacks = allCallbacks.filter(callback =>
            callback.id &&
            typeof callback.id === 'number' &&
            !newCallbackIds.includes(callback.id)
        );

        const errors = [];

        // Save new callbacks
        for (const callback of newCallbacks) {
            try {
                const apiData = mapCallbackToApiFormat(callback);
                // Ensure order is set based on index
                const callbackIndex = allCallbacks.findIndex(cb => cb.id === callback.id);
                if (callbackIndex !== -1) {
                    apiData.order = callbackIndex + 1;
                }

                const response = await CreateActionCallback(
                    LimbChatbot.rest.url,
                    LimbChatbot.rest.nonce,
                    actionId,
                    apiData
                );

                if (response?.id) {
                    // Update the callback with the response
                    if (addEditActionRef.current?.updateCallbackWithResponse) {
                        addEditActionRef.current.updateCallbackWithResponse(callback.id, response);
                    }
                } else {
                    errors.push({
                        type: 'create',
                        callback: callback,
                        error: new Error(__("Failed to create callback. Invalid response.", 'limb-chatbot'))
                    });
                }
            } catch (e) {
                errors.push({
                    type: 'create',
                    callback: callback,
                    error: e
                });
            }
        }

        // Update existing callbacks
        for (const callback of existingCallbacks) {
            try {
                const apiData = mapCallbackToApiFormat(callback);
                // Ensure order is set based on index
                const callbackIndex = allCallbacks.findIndex(cb => cb.id === callback.id);
                if (callbackIndex !== -1) {
                    apiData.order = callbackIndex + 1;
                }

                const response = await UpdateActionCallback(
                    LimbChatbot.rest.url,
                    LimbChatbot.rest.nonce,
                    actionId,
                    callback.id,
                    apiData
                );

                if (!response?.id) {
                    errors.push({
                        type: 'update',
                        callback: callback,
                        error: new Error(__("Failed to update callback. Invalid response.", 'limb-chatbot'))
                    });
                }
            } catch (e) {
                errors.push({
                    type: 'update',
                    callback: callback,
                    error: e
                });
            }
        }

        // Show errors if any occurred
        if (errors.length > 0) {
            const errorMessages = errors.map(err => {
                const callbackName = err.callback?.name || err.callback?.type || __("Unknown callback", 'limb-chatbot');
                const action = err.type === 'create' ? __("create", 'limb-chatbot') : __("update", 'limb-chatbot');
                return `${callbackName}: ${err.error.message || __("Failed to", 'limb-chatbot')} ${action}`;
            }).join('<br/>');

            handleError(new Error(errorMessages), notifications.set, {
                title: __("Some callbacks failed to save.", 'limb-chatbot'),
                description: errorMessages,
            });
        }
    };

    /**
     * Delete callback
     *
     * @param {number} actionId Action ID
     * @param {number} callbackId Callback ID
     * @return {Promise<void>}
     */
    const deleteCallback = async (actionId, callbackId) => {
        try {
            await DeleteActionCallback(
                LimbChatbot.rest.url,
                LimbChatbot.rest.nonce,
                actionId,
                callbackId
            );
        } catch (e) {
            handleError(e, notifications.set, {
                title: __("Failed to delete callback.", 'limb-chatbot'),
                description: e.message ? __(e.message, 'limb-chatbot') : __("Please try again.", 'limb-chatbot'),
            });
            throw e; // Re-throw to stop processing
        }
    };

    /**
     * Fetch actions from API
     *
     * @param {number} page Page number
     * @param {number} perPage Items per page
     * @param {object} order Order parameters (optional, for compatibility)
     */
    const fetchActions = async (page = actionsPagination.page, perPage = actionsPagination.perPage, order = null) => {
        setLoading(prev => prev + 1);
        try {
            // Use provided order or fall back to state
            const orderParams = order || actionsOrder;
            const response = await GetActions(
                LimbChatbot.rest.url,
                LimbChatbot.rest.nonce,
                {
                    page: page,
                    per_page: perPage,
                    include: ['parameters', 'action_callbacks'],
                    orderby: orderParams.orderBy || 'created_at',
                    order: orderParams.order || 'desc'
                }
            );

            // Handle response structure (could be array or object with items/total)
            if (Array.isArray(response)) {
                setActions(response);
                setActionsPagination(prevState => ({
                    ...prevState,
                    page: page,
                    total: response.length,
                }));
            } else if (response?.items) {
                setActions(response.items || []);
                setActionsPagination(prevState => ({
                    ...prevState,
                    page: page,
                    total: +response.total || 0,
                }));
            } else {
                setActions([]);
                setActionsPagination(prevState => ({
                    ...prevState,
                    page: page,
                    total: 0,
                }));
            }
        } catch (e) {
            handleError(e, notifications.set, {
                title: __("Failed to fetch actions.", 'limb-chatbot'),
                description: e.message ? __(e.message, 'limb-chatbot') : __("Please try again.", 'limb-chatbot'),
            });
        } finally {
            setIsDataFetched(true);
            setLoading(prev => prev - 1);
        }
    };

    useEffect(() => {
        // Only refetch actions when order changes, but only if data was already fetched
        if (!addingEditingAction && isDataFetched) {
            fetchActions(actionsPagination.page, actionsPagination.perPage, actionsOrder);
        }
    }, [actionsOrder]);

    // Initial fetch on mount
    useEffect(() => {
        if (!isDataFetched) {
            fetchActions(actionsPagination.page, actionsPagination.perPage, actionsOrder);
        }
    }, []);

    // Check for query parameters to auto-open entries or edit view
    useEffect(() => {
        const handleQueryParams = () => {
            const urlParams = new URLSearchParams(window.location.search);
            const actionId = urlParams.get('action_id');
            const view = urlParams.get('view');

            // Wait for actions to be fetched first
            if (!isDataFetched) {
                return;
            }

            // Handle view=entries
            if (view === 'entries' && actionId) {
                const numericActionId = parseInt(actionId, 10);

                // Find the action in the loaded actions
                const action = actions.find(a => a.id === numericActionId);

                if (action) {
                    // Auto-open entries for this action (don't call toggleShowEntries to avoid URL update)
                    setShowEntries(true);
                    setSelectedAction(action);
                    setAddingEditingAction(false);
                } else {
                    // If action not found in current page, try to fetch it directly
                    setLoading(prev => prev + 1);
                    GetAction(
                        LimbChatbot.rest.url,
                        LimbChatbot.rest.nonce,
                        numericActionId,
                        {
                            include: ['parameters', 'action_callbacks']
                        }
                    ).then(fullAction => {
                        setShowEntries(true);
                        setSelectedAction(fullAction);
                        setAddingEditingAction(false);
                    }).catch(e => {
                        handleError(e, notifications.set, {
                            title: __("Failed to load action.", 'limb-chatbot'),
                            description: e.message ? __(e.message, 'limb-chatbot') : __("Please check and try again.", 'limb-chatbot'),
                        });
                    }).finally(() => {
                        setLoading(prev => prev - 1);
                    });
                }
            }
            // Handle view=edit
            else if (view === 'edit' && actionId) {
                const numericActionId = parseInt(actionId, 10);

                // First check if action exists in the loaded actions list
                const action = actions.find(a => a.id === numericActionId);

                if (action) {
                    // Action found in list, fetch full details and open edit
                    setLoading(prev => prev + 1);
                    GetAction(
                        LimbChatbot.rest.url,
                        LimbChatbot.rest.nonce,
                        numericActionId,
                        {
                            include: ['parameters', 'action_callbacks']
                        }
                    ).then(fullAction => {
                        setSelectedAction(fullAction);
                        setAddingEditingAction(true);
                        setActiveTab('basic-info');
                        setShowEntries(false);
                        wasJustCreated.current = false;
                    }).catch(e => {
                        handleError(e, notifications.set, {
                            title: __("Failed to load action.", 'limb-chatbot'),
                            description: e.message ? __(e.message, 'limb-chatbot') : __("Please check and try again.", 'limb-chatbot'),
                        });
                    }).finally(() => {
                        setLoading(prev => prev - 1);
                    });
                } else {
                    // If action not found in current page, try to fetch it directly
                    setLoading(prev => prev + 1);
                    GetAction(
                        LimbChatbot.rest.url,
                        LimbChatbot.rest.nonce,
                        numericActionId,
                        {
                            include: ['parameters', 'action_callbacks']
                        }
                    ).then(fullAction => {
                        setSelectedAction(fullAction);
                        setAddingEditingAction(true);
                        setActiveTab('basic-info');
                        setShowEntries(false);
                        wasJustCreated.current = false;
                    }).catch(e => {
                        handleError(e, notifications.set, {
                            title: __("Failed to load action.", 'limb-chatbot'),
                            description: e.message ? __(e.message, 'limb-chatbot') : __("Please check and try again.", 'limb-chatbot'),
                        });
                    }).finally(() => {
                        setLoading(prev => prev - 1);
                    });
                }
            }
            // Handle view=add (new action)
            else if (view === 'add' && !actionId) {
                setAddingEditingAction(true);
                setSelectedAction(null);
                setActiveTab('basic-info');
                setShowEntries(false);
                wasJustCreated.current = false;
            }
            // No view parameter - show main list
            else if (!view) {
                setShowEntries(false);
                setAddingEditingAction(false);
                setSelectedAction(null);
                setActiveTab('basic-info');
                wasJustCreated.current = false;
            }
        };

        // Handle initial load and URL changes
        handleQueryParams();

        // Listen for browser back/forward navigation
        const handlePopState = () => {
            handleQueryParams();
        };

        window.addEventListener('popstate', handlePopState);

        return () => {
            window.removeEventListener('popstate', handlePopState);
        };
    }, [isDataFetched, actions]);

    // Sync unsaved changes state from AddEdit component
    useEffect(() => {
        if (addingEditingAction && addEditActionRef.current) {
            // Check for unsaved changes
            const hasChanges = addEditActionRef.current?.hasUnsavedChanges?.() || false;
            setHasUnsavedChanges(hasChanges);
        } else {
            // Reset when not editing
            setHasUnsavedChanges(false);
        }
    }, [addingEditingAction, activeTab, selectedAction]);

    // Also check on a reasonable interval to catch state changes in AddEdit component
    useEffect(() => {
        if (!addingEditingAction) {
            return;
        }

        const interval = setInterval(() => {
            if (addEditActionRef.current) {
                const hasChanges = addEditActionRef.current?.hasUnsavedChanges?.() || false;
                setHasUnsavedChanges(prev => {
                    // Only update if changed to avoid unnecessary re-renders
                    return prev !== hasChanges ? hasChanges : prev;
                });
            }
        }, 300);

        return () => clearInterval(interval);
    }, [addingEditingAction]);

    // Observe ContentBody height changes for custom rendering pages
    useEffect(() => {
        if (!updatePositions) {
            return;
        }

        const contentBodyElement = document.querySelector('.lbaic-settings-content-body');
        if (!contentBodyElement || !window.ResizeObserver) {
            return;
        }

        const resizeObserver = new ResizeObserver(() => {
            window.requestAnimationFrame(updatePositions);
        });

        resizeObserver.observe(contentBodyElement);

        return () => {
            resizeObserver.disconnect();
        };
    }, [updatePositions, addingEditingAction]);

    const handleAddNewAction = () => {
        setAddingEditingAction(true);
        setSelectedAction(null);
        setActiveTab('basic-info');
        // Reset wasJustCreated flag when adding new action
        wasJustCreated.current = false;

        // Add query params to URL for new action
        const url = new URL(window.location);
        url.searchParams.set('view', 'add');
        url.searchParams.delete('action_id'); // Remove action_id for new actions
        window.history.pushState({}, '', url);
    };

    const toggleShowEntries = (action) => {
        if (action) {
            setShowEntries(true);
            setSelectedAction(action);
            // Add query params to URL
            const url = new URL(window.location);
            url.searchParams.set('action_id', action.id);
            url.searchParams.set('view', 'entries');
            window.history.pushState({}, '', url);
        } else {
            setShowEntries(false);
            setSelectedAction(null);
            // Remove query params from URL
            const url = new URL(window.location);
            url.searchParams.delete('action_id');
            url.searchParams.delete('view');
            window.history.pushState({}, '', url);
        }
    }

    /**
     * Handle edit action
     *
     * @param {object} action Action to edit
     */
    const handleEditAction = async (action) => {
        setLoading(prev => prev + 1);
        try {
            // Fetch full action data with parameters and callbacks
            const fullAction = await GetAction(
                LimbChatbot.rest.url,
                LimbChatbot.rest.nonce,
                action.id,
                {
                    include: ['parameters', 'action_callbacks']
                }
            );
            setSelectedAction(fullAction);
            setAddingEditingAction(true);
            setActiveTab('basic-info');
            // Reset wasJustCreated flag when editing existing action
            wasJustCreated.current = false;

            // Add query params to URL
            const url = new URL(window.location);
            url.searchParams.set('action_id', fullAction.id);
            url.searchParams.set('view', 'edit');
            window.history.pushState({}, '', url);
        } catch (e) {
            handleError(e, notifications.set, {
                title: __("Failed to load action.", 'limb-chatbot'),
                description: e.message ? __(e.message, 'limb-chatbot') : __("Please try again.", 'limb-chatbot'),
            });
        } finally {
            setLoading(prev => prev - 1);
        }
    };

    /**
     * Handle delete action
     *
     * @param {object} action Action to delete
     */
    const handleDeleteAction = async (action) => {
        if (await confirm(__("Are you sure you want to delete this action?", 'limb-chatbot'))) {
            setDeleting(true);
            try {
                await DeleteAction(
                    LimbChatbot.rest.url,
                    LimbChatbot.rest.nonce,
                    action.id
                );

                // Remove action ID from action_ids array if it exists
                const currentActionIds = [...settings['action_ids'][0]];
                if (currentActionIds.includes(action.id)) {
                    const newActionIds = currentActionIds.filter(id => id !== action.id);

                    // Update chatbot action_ids setting
                    try {
                        await UpdateSetting(
                            LimbChatbot.rest.url,
                            LimbChatbot.rest.nonce,
                            'lbaic.utilities.chatbot.action_ids',
                            newActionIds
                        );
                    } catch (e) {
                        // Log error but don't fail the entire delete operation
                        handleWarning(e);
                    }

                    // Update local state immediately
                    settings['action_ids'][1](newActionIds);

                    // Also update sessionStorage that TabSettings uses
                    // This ensures TabSettings' useEffect sees the change and updates its initialData
                    try {
                        const storageKey = `lbaic.${TAB_NAME}`;
                        const storageData = JSON.parse(sessionStorage.getItem(storageKey) || '{}');
                        storageData['action_ids'] = newActionIds;
                        sessionStorage.setItem(storageKey, JSON.stringify(storageData));
                    } catch (e) {
                        // Ignore sessionStorage errors
                        handleWarning(e);
                    }
                }

                handleSuccess(notifications.set, {
                    title: __("Action deleted successfully.", 'limb-chatbot'),
                });
                // Handle pagination after deletion
                handlePaginationAfterDeletion({
                    currentItemsCount: actions.length,
                    deletedCount: 1,
                    pagination: actionsPagination,
                    fetchFunction: fetchActions,
                    setItems: setActions,
                    setPagination: setActionsPagination,
                    deletedIds: [action.id]
                });
            } catch (e) {
                handleError(e, notifications.set, {
                    title: __("Failed to delete action.", 'limb-chatbot'),
                    description: e.message ? __(e.message, 'limb-chatbot') : __("Please try again.", 'limb-chatbot'),
                });
            } finally {
                setDeleting(false);
            }
        }
    };

    /**
     * Handle toggle status (local state only, save with TabSettings button)
     *
     * @param {object} action Action to toggle
     */
    const handleToggleStatus = (action) => {
        const currentActionIds = [...settings['action_ids'][0]];
        const actionId = action.id;
        const isCurrentlyEnabled = currentActionIds.includes(actionId);

        // Toggle: remove if enabled, add if disabled
        let newActionIds;
        if (isCurrentlyEnabled) {
            // Remove from array
            newActionIds = currentActionIds.filter(id => id !== actionId);
        } else {
            // Add to array
            newActionIds = [...currentActionIds, actionId];
        }

        // Update local state only (will be saved with TabSettings Save button)
        settings['action_ids'][1](newActionIds);
    };

    const save = async (options = {}) => {
        const {autosave = false} = options;
        setSaving(true);

        try {
            // If on configuration tab, only save parameters and callbacks
            if (activeTab === 'configuration') {
                if (!selectedAction?.id) {
                    throw new Error(__("Cannot save configuration. Action must be created first.", 'limb-chatbot'));
                }

                // Validate all parameters and callbacks before saving
                const parameterErrors = addEditActionRef.current?.validateAllParameters() || [];
                const callbackErrors = addEditActionRef.current?.validateAllCallbacks() || [];

                // If there are validation errors, open accordions for items with errors
                if (parameterErrors.length > 0 || callbackErrors.length > 0) {
                    // Open accordions for parameters with errors
                    if (parameterErrors.length > 0 && addEditActionRef.current?.setOpenedParameterIds) {
                        const errorIds = new Set(parameterErrors.map(err => err.id));
                        addEditActionRef.current.setOpenedParameterIds(errorIds);
                    }

                    // Open accordions for callbacks with errors
                    if (callbackErrors.length > 0 && addEditActionRef.current?.setOpenedCallbackIds) {
                        const errorIds = new Set(callbackErrors.map(err => err.id));
                        addEditActionRef.current.setOpenedCallbackIds(errorIds);
                    }

                    // Show error message
                    const errorCount = parameterErrors.length + callbackErrors.length;
                    handleError(new Error(__("Please fix the errors before saving.", 'limb-chatbot')), notifications.set, {
                        title: __("Validation failed", 'limb-chatbot'),
                        description: sprintf(__("Found %d error(s) in parameters and callbacks. Please review and fix them.", 'limb-chatbot'), errorCount),
                    });
                    setSaving(false);
                    return;
                }

                // Clear opened states if validation passed
                if (addEditActionRef.current?.setOpenedParameterIds) {
                    addEditActionRef.current.setOpenedParameterIds(new Set());
                }
                if (addEditActionRef.current?.setOpenedCallbackIds) {
                    addEditActionRef.current.setOpenedCallbackIds(new Set());
                }

                // Save new parameters if any
                try {
                    await saveNewParameters(selectedAction.id);
                } catch (e) {
                    // Error already handled in saveNewParameters
                }

                // Save callbacks (new and updated) if any
                try {
                    await saveCallbacks(selectedAction.id);
                } catch (e) {
                    // Error already handled in saveCallbacks
                }

                // If action was just created, add it to chatbot action_ids array
                // Skip this step if autosave is true (don't publish if not published yet)
                if (wasJustCreated.current && !autosave) {
                    try {
                        const currentActionIds = [...settings['action_ids'][0]];
                        const actionId = selectedAction.id;

                        // Only add if not already in the array
                        if (!currentActionIds.includes(actionId)) {
                            const newActionIds = [...currentActionIds, actionId];

                            // Update chatbot action_ids setting
                            await UpdateSetting(
                                LimbChatbot.rest.url,
                                LimbChatbot.rest.nonce,
                                'lbaic.utilities.chatbot.action_ids',
                                newActionIds
                            );

                            // Update local state immediately
                            settings['action_ids'][1](newActionIds);
                            initialDataRef.current['action_ids'] = newActionIds;

                            // Also update sessionStorage that TabSettings uses
                            // This ensures TabSettings' useEffect sees the change and updates its initialData
                            try {
                                const storageKey = `lbaic.${TAB_NAME}`;
                                const storageData = JSON.parse(sessionStorage.getItem(storageKey) || '{}');
                                storageData['action_ids'] = newActionIds;
                                sessionStorage.setItem(storageKey, JSON.stringify(storageData));
                            } catch (e) {
                                // Ignore sessionStorage errors
                                handleWarning(e);
                            }
                        }

                        // Reset the flag only after successful connection
                        wasJustCreated.current = false;
                    } catch (e) {
                        // Log error but don't fail the entire save operation
                        // User can manually connect the action if auto-connect fails
                        handleError(e, notifications.set, {
                            title: __("Action saved, but failed to auto-connect to chatbot.", 'limb-chatbot'),
                            description: __("You can manually connect this action to the chatbot from the actions list.", 'limb-chatbot'),
                        });
                        // Don't reset flag so it can try again if user saves configurations again
                    }
                } else if (wasJustCreated.current && autosave) {
                    // If autosave, don't reset the flag so it can be published later
                    // Just mark that we've saved the configuration
                }

                // Only show success message if not autosaving
                if (!autosave) {
                    handleSuccess(notifications.set, {
                        title: __("Configuration saved successfully.", 'limb-chatbot'),
                    });
                }

                // Reset initial data to clear unsaved changes flag
                if (addEditActionRef.current?.resetInitialData) {
                    addEditActionRef.current.resetInitialData();
                }
                // Update unsaved changes state
                setHasUnsavedChanges(false);

                // Refresh actions list
                await fetchActions();
            } else {
                // If on basic-info tab, save/update the action
                const data = addEditActionRef.current?.getDataToSave();
                if (!data) {
                    // Errors are already shown
                    setSaving(false);
                    return;
                }

                // If no action created yet, create the action
                if (!selectedAction?.id) {
                    // Prepare request data with title and ai_instructions
                    const requestData = {
                        title: data.title,
                        ai_instructions: data.ai_instructions
                    };

                    // Create the action via API
                    const response = await CreateAction(
                        LimbChatbot.rest.url,
                        LimbChatbot.rest.nonce,
                        requestData
                    );

                    if (response?.id) {
                        // Mark as created and switch to configuration tab
                        if (addEditActionRef.current?.markAsCreated) {
                            addEditActionRef.current.markAsCreated();
                        }
                        setSelectedAction(response);
                        setActiveTab('configuration');
                        // Track that this action was just created
                        wasJustCreated.current = true;

                        handleSuccess(notifications.set, {
                            title: __("Action created successfully.", 'limb-chatbot'),
                        });

                        // Reset initial data to clear unsaved changes flag
                        if (addEditActionRef.current?.resetInitialData) {
                            addEditActionRef.current.resetInitialData();
                        }
                        // Update unsaved changes state
                        setHasUnsavedChanges(false);
                    } else {
                        throw new Error(__("Failed to create action. Invalid response.", 'limb-chatbot'));
                    }
                } else {
                    // Update existing action
                    // Prepare request data with title and ai_instructions
                    const requestData = {
                        title: data.title,
                        ai_instructions: data.ai_instructions
                    };

                    // Update the action via API
                    const response = await UpdateAction(
                        LimbChatbot.rest.url,
                        LimbChatbot.rest.nonce,
                        selectedAction.id,
                        requestData
                    );

                    if (response?.id) {
                        // Update the selected action with the response
                        setSelectedAction(response);

                        // Switch to configuration tab
                        setActiveTab('configuration');

                        handleSuccess(notifications.set, {
                            title: __("Action updated successfully.", 'limb-chatbot'),
                        });

                        // Reset initial data to clear unsaved changes flag
                        if (addEditActionRef.current?.resetInitialData) {
                            addEditActionRef.current.resetInitialData();
                        }
                        // Update unsaved changes state
                        setHasUnsavedChanges(false);
                    } else {
                        throw new Error(__("Failed to update action. Invalid response.", 'limb-chatbot'));
                    }
                }
            }
        } catch (e) {
            handleError(e, notifications.set, {
                title: __("Failed to save.", 'limb-chatbot'),
                description: e.message ? __(e.message, 'limb-chatbot') : __("Please try again.", 'limb-chatbot'),
            });
        } finally {
            setSaving(false);
        }
    };

    const cancelAddingEditing = () => {
        setAddingEditingAction(false);
        setSelectedAction(null);
        setActiveTab('basic-info');
        setHasUnsavedChanges(false);
        wasJustCreated.current = false;

        // Remove query params from URL
        const url = new URL(window.location);
        url.searchParams.delete('action_id');
        url.searchParams.delete('view');
        window.history.pushState({}, '', url);

        // Update actions list
        fetchActions();
    };

    const tableStructure = {
        columns: [
            {
                id: 'title',
                label: __("Title", 'limb-chatbot'),
                className: false,
                render: null,
                sortable: true,
                value: {
                    className: false,
                    value: (row, index) => row.title,
                },
            },
            {
                id: 'handlers',
                label: null,
                className: false,
                render: null,
                value: {
                    className: false,
                    render: (row, index) => {
                        // Handle both callbacks and action_callbacks, and both array and object formats
                        // Prioritize action_callbacks as that's what the API returns
                        let callbacks = [];
                        const callbacksSource = row.action_callbacks
                        if (callbacksSource) {
                            if (Array.isArray(callbacksSource)) {
                                callbacks = callbacksSource;
                            } else if (callbacksSource.items && Array.isArray(callbacksSource.items)) {
                                callbacks = callbacksSource.items;
                            }
                        }

                        if (callbacks.length === 0) {
                            return null;
                        }
                        return (
                            <div className="lbaic-settings-actions-handlers-icons">
                                {callbacks.map((callback, callbackIndex) => {
                                    return (
                                        <div
                                            key={callback.id || callbackIndex}
                                            className="lbaic-settings-actions-handlers-icon"
                                            title={callback.type}
                                            style={{
                                                zIndex: callbacks.length - callbackIndex,
                                            }}
                                        >
                                            {callback.type === 'slack' ? (
                                                <svg
                                                    xmlns="http://www.w3.org/2000/svg"
                                                    width="24"
                                                    height="24"
                                                    viewBox="0 0 24 24">
                                                    <use href="#lbaic-settings-integration-slack"/>
                                                </svg>
                                            ) : (
                                                <svg
                                                    xmlns="http://www.w3.org/2000/svg"
                                                    width="24"
                                                    height="24"
                                                    viewBox="0 0 24 24"
                                                    fill="none"
                                                    stroke="currentColor"
                                                    strokeWidth="2"
                                                    strokeLinecap="round"
                                                    strokeLinejoin="round">
                                                    <use href={`#lbaic-settings-callback-type-${callback.type}`}/>
                                                </svg>
                                            )}
                                        </div>
                                    );
                                })}
                            </div>
                        );
                    },
                },
            },
            {
                id: 'status',
                label: null,
                className: false,
                render: null,
                value: {
                    className: false,
                    render: (row, index) => {
                        // Check if action ID is in the action_ids array
                        const isActive = settings['action_ids'][0].includes(row.id);

                        // Disable toggle if action is not active and has no parameters and no callbacks
                        const isDisabled = !isActive && !row.parameters?.total && !row.action_callbacks?.total;

                        const toggleButton = (
                            <ToggleButton
                                isActive={isActive}
                                onClick={() => handleToggleStatus(row)}
                                disabled={isDisabled}
                            />
                        );

                        // Wrap with tooltip if disabled
                        if (isDisabled) {
                            return (
                                <Tooltip
                                    label={__("The action has no parameters and no callbacks.", 'limb-chatbot')}
                                    className='no-hover-bg'
                                >
                                    {toggleButton}
                                </Tooltip>
                            );
                        }

                        return toggleButton;
                    },
                },
            },
            {
                id: 'actions',
                label: false,
                className: false,
                render: null,
                value: {
                    className: 'lbaic-settings-table-card-floating',
                    render: (row, index) => (
                        <div className='lbaic-settings-table-card-actions'>
                            <Tooltip
                                label={__("View entries", 'limb-chatbot')}
                                className='no-hover-bg'
                                width={100}
                            >
                                <button
                                    onClick={() => toggleShowEntries(row)}
                                    className={`lbaic-settings-table-card-actions-in lbaic-settings-button lbaic-settings-button-center lbaic-settings-button-h-32 lbaic-settings-button-minimal${deleting ? ' lbaic-settings-button-disabled' : ''}`}>
                                    <svg className='lbaic-settings-button-i' xmlns='http://www.w3.org/2000/svg'
                                         fill='none'
                                         viewBox='0 0 24 24'>
                                        <use href='#lbaic-settings-database'/>
                                    </svg>
                                </button>
                            </Tooltip>
                            <Tooltip
                                label={__("Edit action", 'limb-chatbot')}
                                className='no-hover-bg'
                                width={100}
                            >
                                <button
                                    onClick={() => handleEditAction(row)}
                                    className={`lbaic-settings-table-card-actions-in lbaic-settings-button lbaic-settings-button-center lbaic-settings-button-h-32 lbaic-settings-button-minimal${deleting ? ' lbaic-settings-button-disabled' : ''}`}>
                                    <svg className='lbaic-settings-button-i' xmlns='http://www.w3.org/2000/svg'
                                         fill='none'
                                         viewBox='0 0 24 24'>
                                        <use href='#lbaic-settings-edit'/>
                                    </svg>
                                </button>
                            </Tooltip>
                            <Tooltip
                                label={__("Delete action", 'limb-chatbot')}
                                className='no-hover-bg'
                                width={100}
                            >
                                <button
                                    onClick={() => handleDeleteAction(row)}
                                    className={`lbaic-settings-table-card-actions-in lbaic-settings-button lbaic-settings-button-center lbaic-settings-button-h-32 lbaic-settings-button-minimal${deleting ? ' lbaic-settings-button-disabled' : ''}`}>
                                    <svg className='lbaic-settings-button-i' xmlns='http://www.w3.org/2000/svg'
                                         fill='none'
                                         viewBox='0 0 24 24'>
                                        <use href='#lbaic-settings-delete'/>
                                    </svg>
                                </button>
                            </Tooltip>
                        </div>
                    ),
                },
            },
        ],
    };

    // Adding/editing action view
    if (addingEditingAction) {
        return (
            <AddEdit
                ref={addEditActionRef}
                data={selectedAction}
                loading={loading}
                setLoading={setLoading}
                notifications={notifications}
                activeTab={activeTab}
                setActiveTab={setActiveTab}
                onDeleteCallback={deleteCallback}
                saving={saving}
                onSave={save}
                onDiscard={cancelAddingEditing}
                navigate={navigate}
            />
        );
    }

    // Show entries
    if (showEntries) {
        return (
            <Entries
                action={selectedAction}
                close={toggleShowEntries}
            />
        );
    }

    return (
        <TabSettings
            name={TAB_NAME}
            settings={settings}
            notifications={notifications}
            keysPrefix='lbaic.utilities.chatbot'
            tabLoading={loading}
            updateSaving={value => setListSaving(value)}
            footerChildren={
                <button onClick={handleAddNewAction}
                        className={`lbaic-settings-button lbaic-settings-button-center lbaic-settings-button-h-40 lbaic-settings-button-primary lbaic-settings-content-footer-actions-in lbaic-settings-cb-pw-footer-actions-in${listSaving ? ' lbaic-settings-button-disabled' : ''}`}>
                    <span className='lbaic-settings-button-label'>{__("Add action", 'limb-chatbot')}</span>
                </button>
            }
            initialDataRef={initialDataRef}
        >
            {(loading > 0 && !isDataFetched) ? <ContentLoading/> : null}
            <Container className="lbaic-settings-a-es">
                {isDataFetched && !actions.length ? (
                    <Empty
                        title={__("No actions yet", 'limb-chatbot')}
                        subtitle={__("Start by adding your first action", 'limb-chatbot')}
                        icon="tab-actions">
                        <div className='lbaic-settings-empty-actions'>
                            <button
                                onClick={handleAddNewAction}
                                className='lbaic-settings-button lbaic-settings-button-center lbaic-settings-button-h-40 lbaic-settings-button-primary'>
                                <span className='lbaic-settings-button-label'>{__("Add action", 'limb-chatbot')}</span>
                            </button>
                        </div>
                    </Empty>
                ) : (
                    <>
                        <Table
                            key={`actions-table-${settings['action_ids'][0].join(',')}`}
                            className='lbaic-settings-actions-table'
                            data={actions}
                            structure={tableStructure}
                            loading={loading > 0 && !isDataFetched}
                            pagination={actionsPagination}
                            order={{get: actionsOrder, set: setActionsOrder}}
                            _callback={(page, perPage) => fetchActions(page, perPage)}
                        />
                    </>
                )}
            </Container>
            {children}
        </TabSettings>
    );
}