// (C) 2021-2026 GoodData Corporation
import { isEmpty } from "lodash-es";
import { batchActions } from "redux-batched-actions";
import { call, put, select } from "redux-saga/effects";
import { findSection, getItemIndex, getParentPath, getSectionIndex, serializeLayoutItemPath, updateItemIndex, } from "../../../_staging/layout/coordinates.js";
import { normalizeItemSizeToParent } from "../../../_staging/layout/sizing.js";
import { invalidArgumentsProvided } from "../../events/general.js";
import { layoutSectionItemsAdded } from "../../events/layout.js";
import { selectSettings } from "../../store/config/configSelectors.js";
import { insightsActions } from "../../store/insights/index.js";
import { selectInsightsMap } from "../../store/insights/insightsSelectors.js";
import { tabsActions } from "../../store/tabs/index.js";
import { selectLayout, selectScreen, selectStash } from "../../store/tabs/layout/layoutSelectors.js";
import { resolveIndexOfNewItem } from "../../utils/arrayOps.js";
import { addTemporaryIdentityToWidgets } from "../../utils/dashboardItemUtils.js";
import { resizeParentContainers } from "./containerHeightSanitization.js";
import { validateAndNormalizeWidgetItems, validateAndResolveItemFilterSettings, } from "./validation/itemValidation.js";
import { validateItemPlacement, validateSectionExists } from "./validation/layoutValidation.js";
import { validateAndResolveStashedItems } from "./validation/stashValidation.js";
function validateAndResolveItems(commandCtx) {
    const { ctx, layout, stash, items, cmd: { payload: { itemPath, itemIndex, sectionIndex }, }, } = commandCtx;
    if (itemPath === undefined) {
        if (!validateSectionExists(layout, sectionIndex)) {
            throw invalidArgumentsProvided(ctx, commandCtx.cmd, `Attempting to add items to non-existing layout section at index ${sectionIndex}.`);
        }
        const section = layout.sections[sectionIndex];
        if (!validateItemPlacement(section, itemIndex)) {
            throw invalidArgumentsProvided(ctx, commandCtx.cmd, `Attempting to insert new item at wrong index ${itemIndex}. There are currently ${section.items.length} items.`);
        }
        const stashValidationResult = validateAndResolveStashedItems(stash, items);
        if (!isEmpty(stashValidationResult.missing)) {
            throw invalidArgumentsProvided(ctx, commandCtx.cmd, `Attempting to use non-existing stashes. Identifiers of missing stashes: ${stashValidationResult.missing.join(", ")}`);
        }
        return {
            stashValidationResult,
            section,
        };
    }
    else {
        if (!validateSectionExists(layout, itemPath)) {
            throw invalidArgumentsProvided(ctx, commandCtx.cmd, `Attempting to add items to non-existing layout section at index ${serializeLayoutItemPath(itemPath)}.`);
        }
        const section = findSection(layout, itemPath);
        if (!validateItemPlacement(section, itemPath)) {
            throw invalidArgumentsProvided(ctx, commandCtx.cmd, `Attempting to insert new item at wrong index ${serializeLayoutItemPath(itemPath)}. There are currently ${section.items.length} items.`);
        }
        const stashValidationResult = validateAndResolveStashedItems(stash, items);
        if (!isEmpty(stashValidationResult.missing)) {
            throw invalidArgumentsProvided(ctx, commandCtx.cmd, `Attempting to use non-existing stashes. Identifiers of missing stashes: ${stashValidationResult.missing.join(", ")}`);
        }
        return {
            stashValidationResult,
            section,
        };
    }
}
export function* addSectionItemsHandler(ctx, cmd) {
    const { payload: { items }, } = cmd;
    const commandCtx = {
        ctx,
        cmd,
        items: addTemporaryIdentityToWidgets(items),
        layout: yield select(selectLayout),
        stash: yield select(selectStash),
        availableInsights: yield select(selectInsightsMap),
    };
    const { stashValidationResult, section } = validateAndResolveItems(commandCtx);
    const { payload: { itemPath, sectionIndex, itemIndex, autoResolveDateFilterDataset }, } = cmd;
    const normalizationResult = yield call(validateAndNormalizeWidgetItems, ctx, stashValidationResult, cmd);
    const itemsToAdd = yield call(validateAndResolveItemFilterSettings, ctx, cmd, normalizationResult, autoResolveDateFilterDataset);
    const layoutPath = itemPath === undefined ? [{ sectionIndex, itemIndex }] : itemPath;
    const settings = yield select(selectSettings);
    const screen = yield select(selectScreen);
    const itemsWithNormalizedSize = itemsToAdd.map((item) => {
        const { item: itemWithNormalizedSize } = normalizeItemSizeToParent(item, layoutPath, commandCtx.layout, settings, normalizationResult.resolvedInsights.resolved, screen);
        return itemWithNormalizedSize;
    });
    yield put(batchActions([
        insightsActions.addInsights(normalizationResult.resolvedInsights.loaded),
        tabsActions.addSectionItems({
            layoutPath,
            items: itemsWithNormalizedSize,
            usedStashes: stashValidationResult.existing,
            undo: {
                cmd,
            },
        }),
    ]));
    yield call(resizeParentContainers, getParentPath(layoutPath));
    const originalItemIndex = itemPath === undefined ? itemIndex : getItemIndex(itemPath);
    const newItemIndex = resolveIndexOfNewItem(section.items, originalItemIndex);
    const updatedLayoutPath = itemPath === undefined
        ? [{ sectionIndex, itemIndex: newItemIndex }]
        : updateItemIndex(itemPath, newItemIndex);
    return layoutSectionItemsAdded(ctx, sectionIndex === undefined ? getSectionIndex(updatedLayoutPath) : sectionIndex, newItemIndex, updatedLayoutPath, itemsWithNormalizedSize, stashValidationResult.existing, cmd.correlationId);
}
