// (C) 2021-2026 GoodData Corporation
import { createSelector } from "@reduxjs/toolkit";
import { serializeObjRef } from "@gooddata/sdk-model";
import { isNonExportableError, isNonExportableErrorExceptTooLarge, } from "../../../_staging/errors/errorPredicates.js";
import { createMemoizedSelector } from "../_infra/selectors.js";
import { selectSupportsExportToCsv, selectSupportsExportToXlsx, } from "../backendCapabilities/backendCapabilitiesSelectors.js";
import { selectSettings } from "../config/configSelectors.js";
import { selectCanExecuteRaw, selectCanExportTabular } from "../permissions/permissionsSelectors.js";
import { selectAllAnalyticalWidgets, selectAnalyticalWidgetByRef } from "../tabs/layout/layoutSelectors.js";
import { executionResultsAdapter } from "./executionResultsEntityAdapter.js";
const selectSelf = createSelector((state) => state, (state) => state.executionResults);
const adapterSelectors = executionResultsAdapter.getSelectors(selectSelf);
/**
 * @alpha
 */
export const selectExecutionResultEntities = adapterSelectors.selectEntities;
/**
 * @alpha
 */
export const selectExecutionResult = adapterSelectors.selectById;
/**
 * @alpha
 */
export const selectHasSomeExecutionResult = createSelector(selectExecutionResultEntities, (executionResults) => {
    // Empty results can be resolved as error, so consider error also as resolved
    return Object.values(executionResults).filter((e) => !!e?.executionResult || !!e?.error).length >= 1;
});
/**
 * @alpha
 */
export const selectExecutionResultByRef = createMemoizedSelector((ref) => createSelector(selectExecutionResultEntities, (executionResults) => {
    if (!ref) {
        return undefined;
    }
    const key = serializeObjRef(ref);
    return executionResults[key];
}));
/**
 * Selects the execution result limit breaks for the widget with the given ref.
 *
 * @remarks
 * Limit breaks indicate that the widget's execution hit a row/column/cell limit and only partial
 * data was returned. Returns an empty array when there are no limit breaks or the result is not available.
 *
 * @alpha
 */
export const selectExecutionResultLimitBreaksByRef = createMemoizedSelector((ref) => createSelector(selectExecutionResultByRef(ref), (widgetExecution) => widgetExecution?.limitBreaks ?? []));
/**
 * Selects whether the widget with the given ref returned partial data because an execution limit was reached.
 *
 * @alpha
 */
export const selectHasExecutionResultLimitBreaksByRef = createMemoizedSelector((ref) => createSelector(selectExecutionResultLimitBreaksByRef(ref), (limitBreaks) => limitBreaks.length > 0));
/**
 * Selects whether at least one widget currently on the dashboard returned partial data because an
 * execution limit was reached.
 *
 * @remarks
 * Only execution results of widgets still present on the dashboard layout are considered. Execution results
 * keyed by anything else - removed widgets that left a stale entry behind, or the drill dialog's pseudo
 * ref `@@GDC_DRILL_MODAL` - are ignored, so they cannot keep the dashboard partial-results warning visible.
 *
 * @alpha
 */
export const selectHasAnyExecutionResultLimitBreaks = createSelector(selectExecutionResultEntities, selectAllAnalyticalWidgets, (executionResults, widgets) => {
    const liveWidgetIds = new Set(widgets.map((widget) => serializeObjRef(widget.ref)));
    return Object.entries(executionResults).some(([id, e]) => liveWidgetIds.has(id) && (e?.limitBreaks?.length ?? 0) > 0);
});
/**
 * @alpha
 */
export const selectIsExecutionResultReadyForExportByRef = createMemoizedSelector((ref) => createSelector(selectExecutionResultByRef(ref), selectAnalyticalWidgetByRef(ref), (widgetExecution) => {
    if (!widgetExecution) {
        return false;
    }
    const { isLoading, error, executionResult } = widgetExecution;
    return !!executionResult && !isLoading && !isNonExportableError(error);
}));
/**
 * @alpha
 */
export const selectIsExecutionResultExportableToCsvByRef = createMemoizedSelector((ref) => createSelector(selectSupportsExportToCsv, selectIsExecutionResultReadyForExportByRef(ref), selectCanExportTabular, selectCanExecuteRaw, selectSettings, (supportsCapabilityCsv, isReadyForExport, canExportTabular, canExecuteRaw, settings) => {
    const isExportEnabled = Boolean(settings["enableKPIDashboardExport"] && canExportTabular);
    const isRawExportEnabled = Boolean(isExportEnabled && canExecuteRaw);
    return supportsCapabilityCsv && isReadyForExport && isRawExportEnabled;
}));
/**
 * @alpha
 */
export const selectIsExecutionResultExportableToXlsxByRef = createMemoizedSelector((ref) => createSelector(selectSupportsExportToXlsx, selectIsExecutionResultReadyForExportByRef(ref), selectCanExportTabular, selectSettings, (supportCapabilityXlsx, isReadyForExport, canExportTabular, settings) => {
    const isExportEnabled = Boolean(settings["enableKPIDashboardExport"] && canExportTabular);
    return supportCapabilityXlsx && isReadyForExport && isExportEnabled;
}));
/**
 * @alpha
 */
export const selectIsExecutionResultExportableToPdfByRef = createMemoizedSelector((ref) => createSelector(selectIsExecutionResultReadyForExportByRef(ref), selectCanExportTabular, selectSettings, (isReadyForExport, canExportTabular, settings) => {
    const isExportEnabled = Boolean(settings["enableKPIDashboardExport"] && canExportTabular);
    const isPdfExportEnabled = Boolean(settings.enableNewPdfTabularExport);
    return isReadyForExport && isExportEnabled && isPdfExportEnabled;
}));
/**
 * @alpha
 */
export const selectIsExecutionResultReadyForExportRawByRef = createMemoizedSelector((ref) => createSelector(selectExecutionResultByRef(ref), selectAnalyticalWidgetByRef(ref), (widgetExecution) => {
    if (!widgetExecution) {
        return false;
    }
    const { isLoading, error } = widgetExecution;
    return !isLoading && !isNonExportableErrorExceptTooLarge(error);
}));
/**
 * @alpha
 */
export const selectIsExecutionResultExportableToCsvRawByRef = createMemoizedSelector((ref) => createSelector(selectSupportsExportToCsv, selectIsExecutionResultReadyForExportRawByRef(ref), selectCanExportTabular, selectCanExecuteRaw, selectSettings, (supportsCapabilityCsv, isReadyForExport, canExportTabular, canExecuteRaw, settings) => {
    const isExportEnabled = Boolean(settings["enableKPIDashboardExport"] && canExportTabular);
    const isRawExportEnabled = Boolean(isExportEnabled && canExecuteRaw);
    return supportsCapabilityCsv && isReadyForExport && isRawExportEnabled;
}));
