// (C) 2022-2026 GoodData Corporation
import { useEffect, useMemo } from "react";
import stringify from "json-stable-stringify";
import { insightSetFilters, isInsight, } from "@gooddata/sdk-model";
import { useBackendStrict, useCancelablePromise, useExecutionDataView, useWorkspaceStrict, } from "@gooddata/sdk-ui";
import { useDashboardSelector } from "../../../model/react/DashboardStoreProvider.js";
import { useWidgetFilters } from "../../../model/react/useWidgetFilters.js";
import { selectEnableExecutionCancelling } from "../../../model/store/config/configSelectors.js";
function deriveResultState(effectiveInsightTask, filterQueryTask, dataViewTask) {
    // insight non-success status has precedence, other things cannot run without an insight
    const isInsightNonSuccess = effectiveInsightTask.status === "error" ||
        effectiveInsightTask.status === "loading" ||
        effectiveInsightTask.status === "pending";
    if (isInsightNonSuccess) {
        return {
            error: effectiveInsightTask.error,
            result: undefined,
            status: effectiveInsightTask.status,
        };
    }
    if (filterQueryTask.status === "pending" || dataViewTask.status === "pending") {
        return {
            error: undefined,
            result: undefined,
            status: "pending",
        };
    }
    if (filterQueryTask.status === "running" || dataViewTask.status === "loading") {
        return {
            error: undefined,
            result: undefined,
            status: "loading",
        };
    }
    if (filterQueryTask.status === "error" || dataViewTask.status === "error") {
        return {
            error: (dataViewTask.error ?? filterQueryTask.error),
            result: undefined,
            status: "error",
        };
    }
    return {
        error: undefined,
        result: dataViewTask.result,
        status: "success",
    };
}
/**
 * This hook provides an easy way to read a data view for an insight from a custom widget.
 * It resolves the appropriate filters for the widget based on the filters currently set on the whole dashboard.
 *
 * @public
 */
export function useCustomWidgetInsightDataView({ widget, insight, enableExecutionCancelling, onCancel, onError, onLoading, onPending, onSuccess, }) {
    const backend = useBackendStrict();
    const workspace = useWorkspaceStrict();
    const enableExecutionCancellingFF = useDashboardSelector(selectEnableExecutionCancelling);
    const effectiveExecutionCancelling = enableExecutionCancelling ?? enableExecutionCancellingFF;
    const effectiveInsightTask = useCancelablePromise({
        promise: insight
            ? async () => {
                return isInsight(insight)
                    ? insight
                    : backend
                        .workspace(workspace)
                        .insights()
                        .getInsight(insight);
            }
            : null,
        onCancel,
        onPending,
        onError,
        onLoading,
    }, [backend, workspace, insight]);
    const filterQueryTask = useWidgetFilters(
    // only pass the widget in when the insight is ready to not start the filter query while the insight is loading
    effectiveInsightTask.result ? widget : undefined, effectiveInsightTask.result);
    const insightWithAddedFilters = useMemo(() => effectiveInsightTask.result
        ? insightSetFilters(effectiveInsightTask.result, filterQueryTask.result)
        : undefined, 
    // eslint-disable-next-line react-hooks/exhaustive-deps
    [
        effectiveInsightTask.result,
        /**
         * We use stringified value to avoid setting equal filters. This prevents cascading cache invalidation
         * and expensive re-renders down the line. The stringification is worth it as the filters are usually
         * pretty small thus saving more time than it is taking.
         */
        // eslint-disable-next-line react-hooks/exhaustive-deps
        stringify(filterQueryTask.result),
    ]);
    const insightExecution = useMemo(() => {
        return insightWithAddedFilters
            ? backend.workspace(workspace).execution().forInsight(insightWithAddedFilters)
            : undefined;
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [backend, workspace, insightWithAddedFilters, widget]);
    const dataViewTask = useExecutionDataView({
        execution: insightExecution,
        enableExecutionCancelling: effectiveExecutionCancelling,
        onCancel,
        onError,
        onSuccess,
    });
    useEffect(() => {
        if (filterQueryTask.status === "error") {
            onError?.(filterQueryTask.error);
        }
    }, [filterQueryTask.error, filterQueryTask.status, onError]);
    return deriveResultState(effectiveInsightTask, filterQueryTask, dataViewTask);
}
