'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

var utils$1 = require('../../../../components/_async/async-filters-form/utils.js');
var localsHelper = require('../../../../utils/localsHelper.js');
var utils = require('../../../../components/_filters/utils.js');
var reportStoreHelper = require('../../../../utils/reportStoreHelper.js');
var UserStoreItemBuilder = require('../../../../utils/UserStoreItemBuilder.js');
var UserReports = require('../../../../types/UserReports.js');
var definitionUtils = require('../../../../utils/definitionUtils.js');
var sessionHelper = require('../../../../utils/sessionHelper.js');
var queryMappers = require('../../../../utils/queryMappers.js');
var urlHelper = require('../../../../utils/urlHelper.js');
var utils$2 = require('../../../../components/_async/request-details/utils.js');

// Utils
// ----------------------------------------------------------------------
// POST
// ----------------------------------------------------------------------
/**
 * Sends the request for the async report
 *
 * @param {AsyncReportUtilsParams} { req, res, services }
 * @return {*}
 */
const request = async ({ req, res, services }) => {
    const { token } = localsHelper.default.getValues(res);
    const requestArgs = { req, res, token };
    const { executionData, queryData, childExecutionData } = await requestProduct({
        ...requestArgs,
        services,
    });
    if (executionData.executionId && executionData.tableId) {
        await updateStore({
            req,
            res,
            services,
            queryData,
            executionData,
            childExecutionData,
        });
    }
    else {
        throw new Error('No execution data returned');
    }
    return executionData;
};
/**
 * Updates the store with the request details
 *
 * @param {Request} req
 * @param {Response} res
 * @param {Services} services
 * @param {SetQueryFromFiltersResult} querySummaryData
 * @param {string} executionData
 * @return {*}  {Promise<string>}
 */
const updateStore = async ({ req, res, services, queryData, executionData, childExecutionData, }) => {
    const { search, id, type } = req.body;
    const { dprUser, definitionsPath, dpdPathFromQuery } = localsHelper.default.getValues(res);
    await reportStoreHelper.removeDuplicates({ storeService: services.requestedReportService, userId: dprUser.id, id, search });
    await reportStoreHelper.removeDuplicates({ storeService: services.recentlyViewedService, userId: dprUser.id, id, search });
    const requestFormData = req.body;
    const reportData = {
        type: requestFormData.type,
        reportId: requestFormData.reportId,
        reportName: requestFormData.reportName,
        description: requestFormData.description,
        id: requestFormData.id,
        name: requestFormData.name,
    };
    let requestedReportData;
    switch (type) {
        case UserReports.ReportType.REPORT:
            requestedReportData = new UserStoreItemBuilder.UserStoreItemBuilder(reportData, requestFormData)
                .addExecutionData(executionData)
                .addChildExecutionData(childExecutionData)
                .addFilters(queryData?.filterData)
                .addSortData(queryData?.sortData)
                .addDefinitionsPath(definitionsPath, dpdPathFromQuery)
                .addRequestUrls(req)
                .addQuery(queryData)
                .addStatus(UserReports.RequestStatus.SUBMITTED)
                .addTimestamp()
                .build();
            break;
        case UserReports.ReportType.DASHBOARD: {
            requestedReportData = new UserStoreItemBuilder.UserStoreItemBuilder(reportData, requestFormData)
                .addExecutionData(executionData)
                .addChildExecutionData(childExecutionData)
                .addFilters(queryData?.filterData)
                .addDefinitionsPath(definitionsPath, dpdPathFromQuery)
                .addRequestUrls(req)
                .addQuery(queryData)
                .addStatus(UserReports.RequestStatus.SUBMITTED)
                .addTimestamp()
                .addMetrics(JSON.parse(req.body.sections))
                .build();
            break;
        }
    }
    if (requestedReportData)
        await services.requestedReportService.addReport(dprUser.id, requestedReportData);
};
const requestChildReports = async (childVariants, reportingService, token, reportId, queryData, dataProductDefinitionsPath) => {
    let query;
    if (queryData) {
        query = queryData.query;
        delete query['sortColumn'];
        delete query['sortedAsc'];
    }
    return Promise.all(childVariants.map((childVariant) => reportingService
        .requestAsyncReport(token, reportId, childVariant.id, {
        ...(query && query),
        ...(dataProductDefinitionsPath && { dataProductDefinitionsPath }),
    })
        .then((response) => {
        const { executionId, tableId } = response;
        if (!executionId || !tableId) {
            throw new Error('requestChildReports: No execution of tableId in response');
        }
        return { executionId, tableId, variantId: childVariant.id };
    })));
};
const requestProduct = async ({ req, res, token, services, }) => {
    const { definitionsPath: dataProductDefinitionsPath, dpdPathFromQuery } = localsHelper.default.getValues(res);
    const { reportId, id, type } = req.body;
    const query = queryMappers.formBodyToQueryObject(req.body);
    let executionId;
    let tableId;
    let childVariants = [];
    let sortData;
    const { definition, fields } = await definitionUtils.getDefinitionByType(type, services, token, reportId, id);
    if (type === UserReports.ReportType.REPORT) {
        const requestReportResponse = await services.reportingService.requestAsyncReport(token, reportId, id, {
            ...query,
            dataProductDefinitionsPath,
        });
        executionId = requestReportResponse['executionId'];
        tableId = requestReportResponse['tableId'];
        childVariants = definition.variant.childVariants ?? [];
        sortData = utils$1.buildSortData(req.body);
        sessionHelper.setActiveJourneySortSearch(req, { reportId, id, tableId }, sortData);
    }
    if (type === UserReports.ReportType.DASHBOARD) {
        const requestDashboardResponse = await services.dashboardService.requestAsyncDashboard(token, reportId, id, {
            ...query,
            dataProductDefinitionsPath,
        });
        executionId = requestDashboardResponse['executionId'];
        tableId = requestDashboardResponse['tableId'];
    }
    const querySummary = utils$2.buildQuerySummary(req.body, fields);
    const filterData = utils$1.buildFilterData(req.body);
    const queryData = {
        querySummary,
        filterData,
        query,
        ...(sortData && { sortData }),
    };
    const childExecutionData = await requestChildReports(childVariants, services.reportingService, token, reportId, queryData, dataProductDefinitionsPath);
    const executionData = {
        executionId,
        tableId,
        ...(dpdPathFromQuery && { dataProductDefinitionsPath }),
    };
    return {
        executionData,
        childExecutionData,
        queryData,
    };
};
// ----------------------------------------------------------------------
// ERROR
// ----------------------------------------------------------------------
const getFiltersFromReqBody = (req) => {
    return Object.keys(req.body)
        .filter((attr) => attr.includes('filters.'))
        .filter((attr) => !!req.body[attr])
        .map((attr) => {
        return { name: attr, value: req.body[attr] };
    });
};
// ----------------------------------------------------------------------
// GET
// ----------------------------------------------------------------------
/**
 * Returns the data required for rendering the async filters component
 *
 * @param {AsyncReportUtilsParams} { req, res, dataSources }
 * @return {*}
 */
const renderRequest = async ({ req, res, services, next, }) => {
    try {
        const { reportId, type, id } = req.params;
        const { token, csrfToken, definitionsPath: definitionPath, dprUser } = localsHelper.default.getValues(res);
        const { definition, saveDefaultsEnabled } = res.locals;
        let name = '';
        let reportName = '';
        let description = '';
        let fields = [];
        let sections = [];
        if (type === UserReports.ReportType.REPORT) {
            const reportData = await renderReportRequestData(definition);
            name = reportData.name;
            reportName = reportData.reportName;
            description = reportData.description;
            fields = reportData.fields;
        }
        if (type === UserReports.ReportType.DASHBOARD) {
            const definitionApiArgs = { token, reportId: reportId, definitionPath, services };
            const dashboardData = await renderDashboardRequestData({
                ...definitionApiArgs,
                definition: definition,
            });
            name = dashboardData.name;
            reportName = dashboardData.reportName;
            description = dashboardData.description;
            fields = dashboardData.fields;
            sections = dashboardData.sections;
        }
        const filtersData = await utils.getRequestFilters(req, res, fields);
        const hasDefaults = await services.defaultFilterValuesService.hasDefaults(dprUser.id, reportId, id);
        const reportData = {
            reportName,
            name,
            description,
            reportId,
            id,
            definitionPath,
            csrfToken,
            sections,
            hasDefaults,
            type,
            saveDefaultsEnabled,
        };
        return {
            title: `Request ${type}`,
            filtersDescription: `Customise your ${type} using the filters below and submit your request.`,
            filtersData,
            reportData,
        };
    }
    catch (error) {
        next(error);
        return false;
    }
};
const renderDashboardRequestData = async ({ token, reportId, definitionPath, services, definition, }) => {
    const productDefinitions = await services.reportingService.getDefinitions(token, definitionPath);
    const productDefinition = productDefinitions.find((def) => def.id === reportId);
    const { name, description, sections, filterFields: fields } = definition;
    return {
        reportName: productDefinition?.name || '',
        name: name || '',
        description: description || productDefinition?.description || '',
        sections: sections || [],
        fields: fields || [],
    };
};
const renderReportRequestData = async (definition) => {
    const fields = definitionUtils.getFields(definition);
    return {
        definition,
        reportName: definition.name,
        name: definition.variant.name,
        description: definition.variant.description || definition.description || '',
        template: definition.variant.specification,
        fields,
    };
};
/**
 * Ensures that the request will always contain the correct qs on first render
 *
 * @param {Response} res
 * @param {Request} req
 * @return {*}
 */
const redirectWithDefaults = (res, req) => {
    const effectiveQueryString = setDefaultQueryString(req);
    if (effectiveQueryString && Object.keys(req.query).length === 0) {
        const baseUrl = req.originalUrl.split('?')[0].replace(/\/$/, '');
        res.redirect(`${baseUrl}?${effectiveQueryString}`);
        return true;
    }
    return false;
};
/**
 * Sets the defaults query string for pre-filters
 *
 * @param {Request} req
 * @return {*}
 */
const setDefaultQueryString = (req) => {
    const { id, reportId } = req.params;
    const sessionKey = { id, reportId };
    const defaultFiltersSearch = sessionHelper.getActiveJourneyValue(req, sessionKey, 'defaultFiltersSearch');
    const savedRequestDefaultsSearch = sessionHelper.getActiveJourneyValue(req, sessionKey, 'savedRequestDefaultsSearch');
    const defaultSortQueryString = sessionHelper.getActiveJourneyValue(req, sessionKey, 'defaultSortQueryString');
    // If DPD defaults, use those unless there are saved defaults
    const effectiveQueryString = savedRequestDefaultsSearch && savedRequestDefaultsSearch.length > 0
        ? savedRequestDefaultsSearch
        : defaultFiltersSearch;
    if (defaultSortQueryString && defaultSortQueryString.length > 0) {
        return urlHelper.joinQueryStrings(effectiveQueryString, defaultSortQueryString);
    }
    return effectiveQueryString;
};
var AysncRequestUtils = {
    request,
    renderRequest,
    getFiltersFromReqBody,
};

exports.default = AysncRequestUtils;
exports.getFiltersFromReqBody = getFiltersFromReqBody;
exports.redirectWithDefaults = redirectWithDefaults;
exports.renderRequest = renderRequest;
exports.request = request;
exports.setDefaultQueryString = setDefaultQueryString;
exports.updateStore = updateStore;
//# sourceMappingURL=utils.js.map
