const getEndNlpName = (row) => {
    const nlpMapping = {
        IfCondition: 'EndIfCondition',
        StartForLoop: 'EndForLoop',
        StartIteration: 'EndIteration',
        ElseIfCondition: 'EndElseIfCondition',
        ElseCondition: 'EndElseCondition',
    };
    return nlpMapping[row.nlpName] || row.nlpName;
};
const isElseIfConditions = (row) => {
    return ['ElseIfCondition', 'ElseCondition'].includes(row?.nlpName);
};
const getStepsTableData = (tableData, sectionTitle = 'Steps') => {
    const section = tableData.find((item) => item?.title === sectionTitle);
    return section?.data ?? [];
};
// Memoized block map to avoid recomputation
let cachedBlockMap = null;
let cachedTableData = null;
const getBlockMap = (tableData) => {
    // Check if tableData has changed
    if (cachedTableData === tableData && cachedBlockMap) {
        return cachedBlockMap;
    }
    const getStepData = getStepsTableData(tableData);
    const blockMap = new Map();
    // Returns a key for grouping steps.
    const getBlockKey = (step) => step.specialNlpId ?? step.conditionSearchKey ?? null;
    // Finds the corresponding end row based on the start row.
    const getEndNlpRowData = (row) => {
        const endNlpName = getEndNlpName(row);
        const steps = getStepData;
        if (row?.conditionId !== undefined &&
            row?.conditionSearchKey !== undefined &&
            !row.specialNlpId) {
            const conditionKey = row.conditionId === row.conditionSearchKey
                ? row.conditionId
                : row.conditionSearchKey;
            return (steps.find((item) => item.conditionSearchKey === conditionKey &&
                item.nlpName === endNlpName) || null);
        }
        // For for-loop steps using specialNlpId.
        if (row.specialNlpId) {
            return (steps.find((item) => item.specialNlpId === row.specialNlpId &&
                item.nlpName === endNlpName) || null);
        }
        return null;
    };
    // Retrieves the child step IDs between a start and an end row.
    const getChildIds = (startRow, endRow, childOnly) => {
        const steps = getStepData;
        const startIndex = steps.findIndex((item) => item.stepId === startRow?.stepId);
        const endIndex = steps.findIndex((item) => item.stepId === endRow?.stepId);
        return childOnly
            ? steps.slice(startIndex + 1, endIndex).map((item) => item.stepId)
            : steps.slice(startIndex, endIndex + 1).map((item) => item.stepId);
    };
    getStepData?.forEach((step) => {
        const key = getBlockKey(step);
        if (!key)
            return;
        const blockEntry = blockMap.get(key) || {
            start: null,
            end: null,
            childIds: [],
            allIds: [],
        };
        // If this is a starting special NLP step, determine its matching end and children.
        if (step?.isSpecialNlp && step.name?.startsWith('Start')) {
            blockEntry.start = step;
            const correspondingEndRow = getEndNlpRowData(step);
            if (correspondingEndRow) {
                blockEntry.end = correspondingEndRow;
                blockEntry.childIds = getChildIds(step, correspondingEndRow, true);
                blockEntry.allIds = getChildIds(step, correspondingEndRow, false);
            }
        }
        blockMap.set(key, blockEntry);
    });
    // Cache the result
    cachedBlockMap = blockMap;
    cachedTableData = tableData;
    return blockMap;
};
const getParentConditionKey = (key) => key.includes('/') ? key.split('/').slice(0, -1).join('/') : key;
const getGreatParentConditionKey = (key) => key.includes('/') ? key.split('/')[0] || key : key;
const updateCheckboxStatus = (tableData, row, isChecked, selectedRows, stepPartialSelect, sectionTitle = 'Steps') => {
    // Create a new Set from the current selection for the given section.
    const updatedSelectSet = new Set(selectedRows[sectionTitle]);
    // Only run the special NLP handling if we're in the Steps section and the row qualifies.
    if (sectionTitle === 'Steps' &&
        (row?.isSpecialNlp || row?.conditionId || row?.parentSpecialNlpId)) {
        const { updateStepPartialSelect } = handleSpecialNlp(row);
        return {
            updateSelectRow: { ...selectedRows, [sectionTitle]: updatedSelectSet },
            updateStepPartialSelect,
        };
    }
    // For regular rows, update the set based on the isChecked flag.
    isChecked
        ? updatedSelectSet.add(row.stepId)
        : updatedSelectSet.delete(row.stepId);
    return {
        updateSelectRow: { ...selectedRows, [sectionTitle]: updatedSelectSet },
    };
    // ----------------------- Helper functions -----------------------
    function handleSpecialNlp(currentRow) {
        const updateStepPartialSelect = new Set(stepPartialSelect);
        const blockMap = getBlockMap(tableData);
        // Recursively update children based on parent condition.
        const updateIfCondition = (row) => {
            const key = row?.conditionSearchKey;
            const parentKey = getParentConditionKey(key);
            const parentData = blockMap.get(parentKey);
            if (parentData &&
                parentData.start.nlpName === 'IfCondition' &&
                parentData?.start?.marginLeft === 0) {
                updateChild(parentData.start);
            }
            if (parentData?.start?.conditionSearchKey?.includes('/') &&
                (parentData?.start.nlpName !== 'IfCondition' ||
                    parentData?.start?.marginLeft !== 0)) {
                updateIfCondition(parentData.start);
            }
        };
        // Updates the child selection for a given row.
        const updateChild = (row) => {
            if (row?.isSpecialNlp) {
                const key = row?.specialNlpId || row?.conditionSearchKey;
                const blockEntry = key && blockMap.get(key);
                if (blockEntry && Array.isArray(blockEntry.allIds)) {
                    blockEntry.allIds.forEach((id) => {
                        updateStepPartialSelect.delete(id);
                        isChecked ? updatedSelectSet.add(id) : updatedSelectSet.delete(id);
                    });
                }
            }
            else {
                isChecked
                    ? updatedSelectSet.add(row?.stepId)
                    : updatedSelectSet.delete(row?.stepId);
            }
        };
        // Recursively update parent selections based on the current row.
        const updateParent = (updateParentData) => {
            let visited = true;
            const recursiveUpdate = (parentData) => {
                const childIds = parentData?.childIds;
                if (isElseIfConditions(parentData?.start)) {
                    const ifParentId = getGreatParentConditionKey(parentData?.start?.conditionSearchKey);
                    const ifParentData = blockMap.get(ifParentId);
                    const ifStartId = ifParentData?.start?.stepId;
                    const isIfBlockPartial = stepPartialSelect.has(ifStartId);
                    if (isChecked && !isIfBlockPartial)
                        updateIfCondition(currentRow);
                }
                if (childIds?.length === 0)
                    return;
                const allChildrenChecked = childIds.every(id => updatedSelectSet.has(id));
                const someChildrenChecked = childIds.some(id => updatedSelectSet.has(id));
                if (allChildrenChecked) {
                    updatedSelectSet.add(parentData.start?.stepId);
                    updatedSelectSet.add(parentData.end?.stepId);
                }
                else {
                    updatedSelectSet.delete(parentData.start?.stepId);
                    updatedSelectSet.delete(parentData.end?.stepId);
                }
                if (someChildrenChecked && !allChildrenChecked) {
                    updateStepPartialSelect.add(parentData.start?.stepId);
                    updateStepPartialSelect.add(parentData.end?.stepId);
                }
                else {
                    updateStepPartialSelect.delete(parentData.start?.stepId);
                    updateStepPartialSelect.delete(parentData.end?.stepId);
                }
                // Recurse upward if there is a parent reference.
                if (parentData?.start?.parentSpecialNlpId) {
                    const grandParent = blockMap.get(parentData.start.parentSpecialNlpId);
                    if (grandParent)
                        recursiveUpdate(grandParent);
                }
                if (parentData?.start?.conditionSearchKey) {
                    const parentKey = getParentConditionKey(parentData?.start?.conditionSearchKey);
                    const conditionSearchKey = parentData?.start?.conditionSearchKey;
                    const conditionId = parentData?.start?.conditionId;
                    if (conditionSearchKey === conditionId && visited) {
                        visited = false;
                        const grandParent = blockMap.get(parentKey);
                        if (grandParent)
                            recursiveUpdate(grandParent);
                        return;
                    }
                    // Skip if conditionSearchKey equals conditionId.
                    if (conditionSearchKey === conditionId)
                        return;
                    const grandParent = blockMap.get(parentKey);
                    if (grandParent)
                        recursiveUpdate(grandParent);
                    return;
                }
            };
            //isParent if isChild
            if (updateParentData?.conditionSearchKey ===
                updateParentData?.conditionId &&
                !updateParentData?.parentSpecialNlpId &&
                updateParentData?.specialNlpId) {
                const parentData = blockMap.get(updateParentData?.conditionSearchKey);
                if (parentData) {
                    recursiveUpdate(parentData);
                }
                return;
            }
            if (!updateParentData?.conditionSearchKey &&
                !updateParentData?.conditionId &&
                updateParentData?.specialNlpId &&
                !updateParentData?.parentSpecialNlpId) {
                return;
            }
            if (updateParentData?.conditionSearchKey &&
                updateParentData?.conditionSearchKey ===
                    updateParentData?.conditionId &&
                updateParentData?.conditionId &&
                updateParentData?.specialNlpId) {
                const parentData = blockMap.get(updateParentData?.conditionSearchKey);
                if (parentData) {
                    recursiveUpdate(parentData);
                }
            }
            if (updateParentData?.parentSpecialNlpId) {
                const parentData = blockMap.get(updateParentData?.parentSpecialNlpId);
                if (parentData) {
                    recursiveUpdate(parentData);
                }
            }
            if (updateParentData?.conditionSearchKey) {
                // logic --> If user Deselect  only  "If Block" the "Else-if" and "Else Block" Should Deselect
                const realIfBlock = blockMap.get(updateParentData?.conditionSearchKey);
                const allChildIds = realIfBlock.childIds;
                let selectedCount = 0;
                allChildIds.forEach((id) => {
                    if (updatedSelectSet.has(id)) {
                        selectedCount++;
                    }
                });
                const isIfBlockPartial = selectedCount > 0 && selectedCount < allChildIds.length;
                const isIfBlockFullyUnselected = selectedCount === 0;
                const currentKey = updateParentData?.conditionSearchKey;
                const isRootIfCondition = !currentKey.includes('/');
                if (isRootIfCondition &&
                    currentKey &&
                    !isChecked &&
                    !isIfBlockPartial &&
                    isIfBlockFullyUnselected) {
                    const currentId = updateParentData?.conditionId;
                    let siblings = [];
                    if (blockMap && currentId) {
                        for (const [key, value] of blockMap.entries()) {
                            if (key.includes(currentId) && key.includes('/')) {
                                siblings.push(value);
                            }
                        }
                    }
                    // Now remove only ELSE IF or ELSE blocks
                    siblings.forEach(block => {
                        if (['ElseIfCondition', 'ElseCondition'].includes(block.start?.nlpName)) {
                            block.childIds?.forEach((id) => {
                                updatedSelectSet.delete(id);
                                updateStepPartialSelect.delete(id);
                            });
                            updatedSelectSet.delete(block.start.stepId);
                            updatedSelectSet.delete(block.end.stepId);
                            updateStepPartialSelect.delete(block.start.stepId);
                            updateStepPartialSelect.delete(block.end.stepId);
                        }
                    });
                }
                const searchKey = row?.isSpecialNlp &&
                    !isElseIfConditions(updateParentData) &&
                    !row?.specialNlpId
                    ? getParentConditionKey(updateParentData.conditionSearchKey)
                    : updateParentData.conditionSearchKey;
                visited = true;
                const parentData = blockMap.get(searchKey);
                if (parentData) {
                    recursiveUpdate(parentData);
                }
            }
        };
        updateChild(currentRow);
        updateParent(currentRow);
        return { updateStepPartialSelect };
    }
};
function getUpdatedSelectedRows(tableData, prevSelectedRows) {
    const updatedSelected = {};
    tableData.forEach((section) => {
        const currentRowIds = section.data.map((row) => row.stepId);
        const previousSet = prevSelectedRows[section.title] || new Set();
        const newSet = new Set([...previousSet].filter(id => currentRowIds.includes(id)));
        updatedSelected[section.title] = newSet;
    });
    return updatedSelected;
}
function getUpdatedPartialSelect(tableData, prevPartialSelect) {
    const allCurrentIds = tableData.reduce((acc, section) => {
        section.data.forEach((row) => acc.add(row.stepId));
        return acc;
    }, new Set());
    return new Set([...prevPartialSelect].filter(id => allCurrentIds.has(id)));
}
function getUpdatedExpandedRows(tableData, prevExpandedRows, defaultExpanded) {
    const sectionTitlesToExpand = {
        Steps: 'Steps',
        Depends: 'Depends on Scripts',
        PRE: 'Pre Conditions',
        POST: 'Post Conditions',
    };
    const newExpandedRows = {};
    tableData.forEach(section => {
        const title = section.title;
        const wasPreviouslyExpanded = title in prevExpandedRows;
        const shouldExpandByDefault = defaultExpanded === 'All'
            ? Object.values(sectionTitlesToExpand).includes(title)
            : title === sectionTitlesToExpand[defaultExpanded];
        newExpandedRows[title] = wasPreviouslyExpanded
            ? (prevExpandedRows[title] ?? false)
            : shouldExpandByDefault;
    });
    return newExpandedRows;
}
const hasSelectedIds = (rows) => {
    if (!rows)
        return false;
    for (const set of Object.values(rows)) {
        if (set && set.size > 0)
            return true;
    }
    return false;
};
const gettingBlockMap = (tableData, selectedRows, stepPartialSelect) => {
    const dynamicUpdate = getBlockMap(tableData);
    const updatedSelectedRows = new Set(selectedRows.Steps);
    const updateStepPartialSelect = new Set(stepPartialSelect);
    dynamicUpdate?.forEach((blockEntry) => {
        const childIds = blockEntry?.childIds;
        if (childIds?.length === 0)
            return;
        const allChildrenChecked = childIds.every(id => updatedSelectedRows.has(id));
        const someChildrenChecked = childIds.some(id => updatedSelectedRows.has(id));
        if (allChildrenChecked) {
            updatedSelectedRows.add(blockEntry.start.stepId);
            updatedSelectedRows.add(blockEntry.end.stepId);
        }
        else {
            updatedSelectedRows.delete(blockEntry.start.stepId);
            updatedSelectedRows.delete(blockEntry.end.stepId);
        }
        if (isElseIfConditions(blockEntry?.start) &&
            (someChildrenChecked || allChildrenChecked)) {
            const key = blockEntry?.start?.conditionSearchKey;
            const parentKey = getParentConditionKey(key);
            const parentData = dynamicUpdate?.get(parentKey)?.allIds;
            if (parentData?.length === 0)
                return;
            parentData?.forEach((stepId) => {
                updatedSelectedRows.add(stepId);
                updateStepPartialSelect.delete(stepId);
            });
        }
        if (someChildrenChecked && !allChildrenChecked) {
            updateStepPartialSelect.add(blockEntry.start.stepId);
            updateStepPartialSelect.add(blockEntry.end.stepId);
        }
        else {
            updateStepPartialSelect.delete(blockEntry.start.stepId);
            updateStepPartialSelect.delete(blockEntry.end.stepId);
        }
    });
    return {
        updateSelectRow: { ...selectedRows, ['Steps']: updatedSelectedRows },
        updateStepPartialSelect,
    };
};

export { getUpdatedExpandedRows, getUpdatedPartialSelect, getUpdatedSelectedRows, gettingBlockMap, hasSelectedIds, updateCheckboxStatus };
//# sourceMappingURL=handleStepCheckBox.js.map
