import DefinitionUtils from '../utils/definitionUtils.js';
import localsHelper from '../utils/localsHelper.js';
import { isBooleanFlagEnabledOrMissing } from '../services/featureFlagService.js';
import { getFeatureFlagEvaluationSubject, FEATURE_FLAGS } from '../utils/featureFlagsHelper.js';
import setUpNunjucksFilters from '../setUpNunjucksFilters.js';
import { errorRequestHandler } from '../routes/index.js';

const getQueryParamAsString = (query, name) => (query[name] ? query[name].toString() : null);
const getDefinitionsPath = (query) => getQueryParamAsString(query, 'dataProductDefinitionsPath');
const deriveDefinitionsPath = (query) => {
    const definitionsPath = getDefinitionsPath(query);
    if (definitionsPath) {
        return definitionsPath;
    }
    return null;
};
const setupResources = (services, layoutPath, env, config) => {
    return async (req, res, next) => {
        populateValidationErrors(req, res);
        try {
            await setFeatures(res, services.featureFlagService);
            await populateDefinitions(services, req, res, config);
            await setLocalsFromServices(services, res);
            await populateRequestedReports(services, res);
            setUpDprPaths(res);
            setupRequestAwareNunjucks(env, res);
            setUpNunjucksFilters(env);
            return next();
        }
        catch (error) {
            return errorRequestHandler(layoutPath)(error, req, res, next);
        }
    };
};
const setupRequestAwareNunjucks = (env, res) => {
    env.addGlobal('getLocals', () => ({ locals: { ...res.locals, ...res.app.locals } }));
};
const setFeatures = async (res, featureFlagService) => {
    if (res.app.locals['featureFlags'] === undefined) {
        res.app.locals['featureFlags'] = {
            flags: {},
        };
    }
    const subject = getFeatureFlagEvaluationSubject(res);
    res.app.locals['featureFlags'].flags = await featureFlagService.evaluateBooleanFlags(FEATURE_FLAGS, subject);
};
const populateValidationErrors = (req, res) => {
    const errors = req.flash(`DPR_ERRORS`);
    if (errors && errors[0]) {
        res.locals['validationErrors'] = JSON.parse(errors[0]);
    }
};
const populateDefinitions = async (services, req, res, config) => {
    // Get the DPD path from the query
    const { token, dprUser } = localsHelper.getValues(res);
    const dpdPathFromQuery = deriveDefinitionsPath(req.query);
    const dpdPathFromBody = req.body?.dataProductDefinitionsPath;
    const definitionsPathFromQuery = dpdPathFromQuery || dpdPathFromBody;
    if (definitionsPathFromQuery) {
        res.locals['dpdPathFromQuery'] = true;
    }
    // Get the DPD path from the config
    const dpdPathFromConfig = config?.dataProductDefinitionsPath;
    if (dpdPathFromConfig) {
        res.locals['dpdPathFromConfig'] = true;
    }
    // query takes presedence over config
    res.locals['definitionsPath'] = (definitionsPathFromQuery || dpdPathFromConfig); // one of these should be populated
    res.locals['pathSuffix'] = `?dataProductDefinitionsPath=${res.locals['definitionsPath']}`;
    let selectedProductCollectionId;
    if (token) {
        selectedProductCollectionId = await services.productCollectionStoreService.getSelectedProductCollectionId(dprUser.id);
    }
    res.locals['definitions'] =
        (await Promise.all([
            services.reportingService.getDefinitions(token, res.locals['definitionsPath']),
            selectedProductCollectionId &&
                services.productCollectionService.getProductCollection(token, selectedProductCollectionId),
        ]).then(([defs, selectedProductCollection]) => {
            if (selectedProductCollection && selectedProductCollection) {
                const productIds = selectedProductCollection.products.map((product) => product.productId);
                return defs.filter((def) => productIds.includes(def.id));
            }
            return defs;
        })) ?? [];
};
const setLocalsFromServices = async (services, res) => {
    const { dprUser } = localsHelper.getValues(res);
    if (dprUser.id) {
        res.locals['downloadingEnabled'] = services.downloadPermissionService.enabled;
        res.locals['bookmarkingEnabled'] = services.bookmarkService.enabled;
        res.locals['collectionsEnabled'] = services.productCollectionService.enabled;
        res.locals['requestMissingEnabled'] = services.missingReportService.enabled;
        // If saveDefaultsEnabled is turned off by feature flag, overwrite all other privileges,
        // otherwise let the defaultFilterValuesService decide.
        const saveDefaultsEnabledFlag = isBooleanFlagEnabledOrMissing('saveDefaultsEnabled', res.app);
        res.locals.saveDefaultsEnabled = saveDefaultsEnabledFlag ? services.defaultFilterValuesService.enabled : false;
    }
};
const populateRequestedReports = async (services, res) => {
    const { dprUser } = localsHelper.getValues(res);
    if (dprUser.id) {
        const { definitions, definitionsPath } = res.locals;
        const recent = await services.recentlyViewedService.getAllReports(dprUser.id);
        await services.requestedReportService.cleanList(dprUser.id, recent);
        const requested = await services.requestedReportService.getAllReports(dprUser.id);
        res.locals['requestedReports'] = !definitionsPath
            ? requested
            : requested.filter((report) => {
                return DefinitionUtils.getCurrentVariantDefinition(definitions, report.reportId, report.id);
            });
        res.locals['recentlyViewedReports'] = !definitionsPath
            ? recent
            : recent.filter((report) => {
                return DefinitionUtils.getCurrentVariantDefinition(definitions, report.reportId, report.id);
            });
        if (res.locals['bookmarkingEnabled']) {
            const bookmarks = await services.bookmarkService.getAllBookmarks(dprUser.id);
            res.locals['bookmarks'] = !definitionsPath
                ? bookmarks
                : bookmarks.filter((bookmark) => {
                    return DefinitionUtils.getCurrentVariantDefinition(definitions, bookmark.reportId, bookmark.id);
                });
        }
    }
};
const setUpDprPaths = (res) => {
    res.app.locals.dprPaths ??= {
        bookmarkActionEndpoint: '/dpr/my-reports/bookmarks',
        downloadActionEndpoint: '/dpr/download-report/',
        productCollectionEndpoint: '/dpr/product-collection/selected',
        bookmarkListPath: '/dpr/my-reports/bookmarks/list',
        requestedListPath: '/dpr/my-reports/requested-reports/list',
        recentlyViewedListPath: '/dpr/my-reports/recently-viewed/list',
        reportsCatalogue: '/dpr/report-catalogue',
        userReportsList: '/dpr/my-reports',
        dprHomepage: '/dpr',
    };
};

export { setupResources as default, setupResources };
//# sourceMappingURL=setUpDprResources.js.map
