// (C) 2026 GoodData Corporation
import { useCallback, useMemo, useState } from "react";
import { mapValues } from "lodash-es";
import { DashboardParameterModeValues, areObjRefsEqual, objRefToString, } from "@gooddata/sdk-model";
import { exportParametersToValues, getAutomationExportParametersByTab, } from "../../../../_staging/automation/index.js";
import { useDashboardSelector } from "../../../../model/react/DashboardStoreProvider.js";
import { selectCatalogParameters } from "../../../../model/store/catalog/catalogSelectors.js";
import { selectEnableParameters } from "../../../../model/store/config/configSelectors.js";
import { selectWidgetLocalIdToTabIdMap } from "../../../../model/store/tabs/layout/layoutSelectors.js";
import { selectExportEffectiveParameters, selectSmartPersistedTabsParameters, } from "../../../../model/store/tabs/parameters/parametersSelectors.js";
import { selectTabs } from "../../../../model/store/tabs/tabsSelectors.js";
import { availableAutomationParameters, reconstructAutomationParametersFromExportParameters, shouldStoreExportParameters, toEffectiveParametersByTab, } from "./automationParameters.js";
/**
 * @internal
 */
export function useAutomationExportParameters({ automationToEdit, widget, storeParameters, setParametersWire, }) {
    const parametersEnabled = useDashboardSelector(selectEnableParameters);
    const catalog = useDashboardSelector(selectCatalogParameters);
    const dashboardParametersByTab = useDashboardSelector(selectSmartPersistedTabsParameters);
    const tabs = useDashboardSelector(selectTabs);
    const widgetTabMap = useDashboardSelector(selectWidgetLocalIdToTabIdMap);
    const widgetIds = widget ? [objRefToString(widget.ref)] : undefined;
    const effectiveParametersByTab = useDashboardSelector(selectExportEffectiveParameters(widgetIds));
    const flatTabId = resolveFlatTabId(widget, widgetTabMap, tabs);
    const shouldStore = shouldStoreExportParameters(!!widget, storeParameters);
    const [editedParametersByTab, setEditedParametersByTab] = useState(() => {
        if (!parametersEnabled) {
            return {};
        }
        const storedByTab = getAutomationExportParametersByTab(automationToEdit);
        return reconstructParametersByTab(storedByTab ?? effectiveParametersByTab, dashboardParametersByTab, catalog);
    });
    // Encodes the gated wire shape and writes it onto the automation — the only path to the document.
    const persistWire = useCallback((parametersByTab, store) => setParametersWire(toEffectiveParametersByTab(parametersByTab, parametersEnabled && store)), [parametersEnabled, setParametersWire]);
    const visibleParametersByTab = useMemo(() => mapValues(editedParametersByTab, (parameters) => parameters.filter(isVisibleParameter)), [editedParametersByTab]);
    const availableParametersByTab = useMemo(() => {
        if (!parametersEnabled) {
            return {};
        }
        // The set of tabs the export covers: the widget's owning tab, or every dashboard tab. Keyed by
        // every in-scope tab (not just seeded ones) so tabs with no current override can still add params.
        const scopeTabIds = widget
            ? flatTabId
                ? [flatTabId]
                : []
            : (tabs ?? []).map((tab) => tab.localIdentifier);
        const result = {};
        for (const tabId of scopeTabIds) {
            // Widget schedules seed addable chips from the widget-effective values, mirroring the alert
            // path; dashboard schedules have no widget context and fall back to dashboard/default
            // inside availableAutomationParameters.
            const widgetParameterValues = widget
                ? exportParametersToValues(effectiveParametersByTab[tabId] ?? [])
                : [];
            result[tabId] = availableAutomationParameters(catalog, editedParametersByTab[tabId] ?? [], dashboardParametersByTab[tabId] ?? [], widgetParameterValues);
        }
        return result;
    }, [
        parametersEnabled,
        widget,
        flatTabId,
        tabs,
        editedParametersByTab,
        catalog,
        dashboardParametersByTab,
        effectiveParametersByTab,
    ]);
    // The fresh per-tab execution set reconstructed from the current dashboard's effective values.
    const parametersForNewAutomation = useMemo(() => parametersEnabled
        ? reconstructParametersByTab(effectiveParametersByTab, dashboardParametersByTab, catalog)
        : {}, [parametersEnabled, effectiveParametersByTab, dashboardParametersByTab, catalog]);
    const applyLatest = useCallback(() => {
        setEditedParametersByTab(parametersForNewAutomation);
        persistWire(parametersForNewAutomation, shouldStore);
    }, [parametersForNewAutomation, persistWire, shouldStore]);
    const onStoreParametersChange = useCallback((nextStoreParameters) => {
        persistWire(editedParametersByTab, nextStoreParameters);
    }, [editedParametersByTab, persistWire]);
    // Patches one tab's parameter execution set by ref, updates the working state, and writes the
    // gated wire shape onto the automation. Edits never touch `hidden`/untouched entries.
    const patchTabParameters = useCallback((tabId, update) => {
        const next = {
            ...editedParametersByTab,
            [tabId]: update(editedParametersByTab[tabId] ?? []),
        };
        setEditedParametersByTab(next);
        persistWire(next, shouldStore);
    }, [editedParametersByTab, persistWire, shouldStore]);
    const onParameterChangeByTab = useCallback((tabId, ref, value) => {
        patchTabParameters(tabId, (current) => current.map((parameter) => areObjRefsEqual(parameter.ref, ref) ? { ...parameter, value } : parameter));
    }, [patchTabParameters]);
    const onParameterDeleteByTab = useCallback((tabId, ref) => {
        patchTabParameters(tabId, (current) => current.filter((parameter) => !areObjRefsEqual(parameter.ref, ref)));
    }, [patchTabParameters]);
    const onParameterAddByTab = useCallback((tabId, ref) => {
        const parameter = availableParametersByTab[tabId]?.find((candidate) => areObjRefsEqual(candidate.ref, ref));
        if (parameter) {
            patchTabParameters(tabId, (current) => [...current, parameter]);
        }
    }, [availableParametersByTab, patchTabParameters]);
    // Flat handlers serve the non-tabbed UI; they delegate to the per-tab ones via `flatTabId`.
    const onParameterChange = useCallback((ref, value) => {
        if (flatTabId) {
            onParameterChangeByTab(flatTabId, ref, value);
        }
    }, [flatTabId, onParameterChangeByTab]);
    const onParameterDelete = useCallback((ref) => {
        if (flatTabId) {
            onParameterDeleteByTab(flatTabId, ref);
        }
    }, [flatTabId, onParameterDeleteByTab]);
    const onParameterAdd = useCallback((ref) => {
        if (flatTabId) {
            onParameterAddByTab(flatTabId, ref);
        }
    }, [flatTabId, onParameterAddByTab]);
    return {
        parametersEnabled,
        visibleParametersByTab,
        availableParametersByTab,
        flatTabId,
        onParameterAdd,
        onParameterChange,
        onParameterDelete,
        onParameterAddByTab,
        onParameterChangeByTab,
        onParameterDeleteByTab,
        applyLatest,
        onStoreParametersChange,
    };
}
function resolveFlatTabId(widget, widgetTabMap, tabs) {
    if (widget) {
        return widget.localIdentifier ? widgetTabMap[widget.localIdentifier] : undefined;
    }
    return (tabs?.length ?? 0) <= 1 ? tabs?.[0]?.localIdentifier : undefined;
}
function isVisibleParameter(parameter) {
    return parameter.mode !== DashboardParameterModeValues.HIDDEN;
}
function reconstructParametersByTab(byTab, dashboardParametersByTab, catalog) {
    return mapValues(byTab, (exportParameters, tabId) => reconstructAutomationParametersFromExportParameters(exportParameters, dashboardParametersByTab[tabId] ?? [], catalog));
}
