'use strict';

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

var queryMappers = require('../../../utils/queryMappers.js');
var urlHelper = require('../../../utils/urlHelper.js');
var localsHelper = require('../../../utils/localsHelper.js');
var utils$1 = require('../../../components/_reports/report-heading/report-columns/report-columns-form/utils.js');
var sessionHelper = require('../../../utils/sessionHelper.js');
var definitionUtils = require('../../../utils/definitionUtils.js');
var UserReports = require('../../../types/UserReports.js');
var utils = require('../../../components/_async/request-details/utils.js');
var UserStoreItemBuilder = require('../../../utils/UserStoreItemBuilder.js');
var types = require('../../../utils/ReportStatus/types.js');

/**
 * Apply interactive query to a REPORT
 *
 * @param {Request} req
 * @param {Response} res
 * @param {Services} services
 * @param {('columns' | 'filters')} applyType
 * @return {*}
 */
const applyReportInteractiveQuery = async (req, res, services, applyType, loadType) => {
    const { reportId, id } = req.params;
    const { token, definitionsPath } = localsHelper.default.getValues(res);
    // Get the definition
    const definition = await services.reportingService.getDefinition(token, reportId, id, definitionsPath);
    const fields = definitionUtils.getFields(definition) || [];
    return applyInteractiveQuery(req, res, applyType, loadType, fields);
};
/**
 * Apply interactive query to a DASHBOARD
 *
 * @param {Request} req
 * @param {Response} res
 * @param {Services} services
 * @param {('columns' | 'filters')} applyType
 * @return {*}
 */
const applyDashboardInteractiveQuery = async (req, res, applyType, loadType) => {
    return applyInteractiveQuery(req, res, applyType, loadType);
};
/**
 * Apply the interactive query
 *
 * @param {Request} req
 * @param {Response} res
 * @param {('columns' | 'filters')} applyType
 * @param {components['schemas']['FieldDefinition'][]} fields
 */
const applyInteractiveQuery = async (req, res, applyType, loadType, fields) => {
    const { tableId, id, reportId } = req.params;
    // Get the stored interactive query data
    const sessionkey = loadType === UserReports.LoadType.ASYNC ? { id, tableId, reportId } : { id, reportId };
    const queryDataFromSession = sessionHelper.getActiveJourneyValue(req, sessionkey, 'currentReportSearch');
    let queryData = {};
    let filtersData = {};
    let columnsData = {};
    if (queryDataFromSession) {
        queryData = queryMappers.qsToQueryObject(queryDataFromSession, '');
        filtersData = queryMappers.qsToQueryObject(queryDataFromSession, 'filters.');
        columnsData = queryMappers.qsToQueryObject(queryDataFromSession, 'columns');
    }
    // Set the query values from the current query
    const preventDefault = queryData?.['preventDefault'];
    const pageSize = queryData?.['pageSize'];
    const selectedPage = applyType === 'columns' ? queryData?.['selectedPage'] : '1';
    const sortColumn = queryData?.['sortColumn'];
    const sortedAsc = queryData?.['sortedAsc'];
    // Create merged form data
    let formData = {
        ...(preventDefault && { preventDefault }),
        ...(selectedPage && { selectedPage }),
        ...(pageSize && { pageSize }),
        ...(sortColumn && { sortColumn }),
        ...(sortedAsc && { sortedAsc }),
        ...(filtersData && filtersData),
        ...(columnsData && columnsData),
    };
    formData =
        applyType === 'columns' && fields
            ? applyColumns(req, queryData, formData, fields)
            : applyFilters(req, queryData, formData);
    const filtersString = queryMappers.queryObjectToQs(formData);
    // Redirect back to report
    res.redirect(`${req.baseUrl}?${filtersString}`);
};
/**
 * Apply columns
 *
 * @param {Request} req
 * @param {(Record<string, string | string[]>)} queryData
 * @param {(Record<string, string | string[]>)} formData
 * @param {components['schemas']['FieldDefinition'][]} fields
 * @return {*}
 */
const applyColumns = (req, queryData, formData, fields) => {
    const { columns: reqColumns } = req.body;
    // Normalize the req columns - should always be an array
    let bodyColumns = [];
    if (reqColumns) {
        bodyColumns = Array.isArray(reqColumns) ? reqColumns : [reqColumns];
    }
    // ensure mandatory cols are present and set the updated columns
    const mandatoryCols = utils$1.default.mandatoryColumns(fields);
    const columns = Array.from(new Set([...mandatoryCols, ...bodyColumns]));
    // Keep the filter values the same as current
    let filters = {};
    if (queryData) {
        filters = Object.keys(queryData)
            .filter((key) => key.includes('filters.'))
            .reduce((acc, key) => ({ ...acc, [key]: queryData[key] }), {});
    }
    return { ...formData, columns, ...filters };
};
/**
 * Apply filters
 *
 * @param {(Record<string, string | string[]>)} queryData
 * @param {(Record<string, string | string[]>)} formData
 * @return {*}
 */
const applyFilters = (req, queryData, formData) => {
    // Ensure current columns stay the same and are normalized
    const columns = queryMappers.normalizeQueryStringArray(queryData?.['columns']) || [];
    const filters = Object.fromEntries(Object.keys(req.body)
        .filter((key) => key.startsWith('filters.'))
        .map((key) => [key, req.body[key]]));
    return { ...formData, ...filters, columns };
};
/**
 * Reset filters action
 *
 * @param {Request} req
 * @param {Response} res
 */
const resetFilters = (req, res, sessionKey) => {
    // Create the reset querystring
    const finalQuery = resetFiltersQueryString(req, sessionKey);
    // Redirect with new query string - query string will handle all rendered elements
    if (finalQuery) {
        res.redirect(`${req.baseUrl}?${finalQuery}`);
    }
};
/**
 * Creates the query string to reset the filters
 *
 * @param {Request} req
 * @param {{ id: string; reportId: string; tableId?: string }} sessionKey
 * @return {*}  {string}
 */
const resetFiltersQueryString = (req, sessionKey) => {
    const defaultSessionKey = { id: sessionKey.id, reportId: sessionKey.reportId };
    const defaultFiltersSearch = sessionHelper.getActiveJourneyValue(req, defaultSessionKey, 'interactiveDefaultFiltersSearch');
    const savedInteractiveDefaultsSearch = sessionHelper.getActiveJourneyValue(req, defaultSessionKey, 'savedInteractiveDefaultsSearch');
    // Set the effective qs: if saved defaults, use those. Otherwise use DPD defaults
    const effectiveQueryString = savedInteractiveDefaultsSearch && savedInteractiveDefaultsSearch.length
        ? savedInteractiveDefaultsSearch
        : defaultFiltersSearch;
    // Get all the current stuff
    const currentColumnsSearch = sessionHelper.getActiveJourneyValue(req, sessionKey, 'currentReportColumnsSearch');
    const currentSortSearch = sessionHelper.getActiveJourneyValue(req, sessionKey, 'currentSortSearch');
    const currentPageSizeSearch = sessionHelper.getActiveJourneyValue(req, sessionKey, 'currentPageSizeSearch');
    // Create the final querystring
    return urlHelper.joinQueryStrings(effectiveQueryString, currentColumnsSearch, currentSortSearch, currentPageSizeSearch);
};
/**
 * Creates the query string to reset the columns
 *
 * @param {Request} req
 * @param {{ id: string; reportId: string; tableId?: string }} sessionKey
 * @return {*}  {string}
 */
const resetColumnsQueryString = (req, sessionKey) => {
    // get the default DPD filters
    const defaultSessionKey = { id: sessionKey.id, reportId: sessionKey.reportId };
    const defaultColumnsSearch = sessionHelper.getActiveJourneyValue(req, defaultSessionKey, 'defaultColumnsSearch');
    // Get all the current stuff
    const currentReportFiltersSearch = sessionHelper.getActiveJourneyValue(req, sessionKey, 'currentReportFiltersSearch');
    const currentSortSearch = sessionHelper.getActiveJourneyValue(req, sessionKey, 'currentSortSearch');
    const currentPageSizeSearch = sessionHelper.getActiveJourneyValue(req, sessionKey, 'currentPageSizeSearch');
    // Create the final querystring
    return urlHelper.joinQueryStrings(defaultColumnsSearch, currentReportFiltersSearch, currentSortSearch, currentPageSizeSearch);
};
/**
 * Creates the default query string
 *
 * @param {Request} req
 * @return {*}  {(string | undefined)}
 */
const createDefaultQueryString = (req) => {
    const { id, reportId, tableId } = req.params;
    // Get the interactive report defaults
    const sessionKey = { id, reportId };
    // Definition defaults
    const defaultFiltersSearch = sessionHelper.getActiveJourneyValue(req, sessionKey, 'interactiveDefaultFiltersSearch');
    const defaultColumnsSearch = sessionHelper.getActiveJourneyValue(req, sessionKey, 'defaultColumnsSearch');
    const defaultSort = sessionHelper.getActiveJourneyValue(req, sessionKey, 'defaultSortQueryString');
    // User defined values
    const savedInteractiveDefaultsSearch = sessionHelper.getActiveJourneyValue(req, sessionKey, 'savedInteractiveDefaultsSearch');
    const requestedSort = sessionHelper.getActiveJourneyValue(req, { id, reportId, tableId }, 'requestedSortSearch');
    /**
     * A report will always have default columns.
     * Redirect when the request has no query params,
     * applying default columns and optional filters.
     */
    const hasIncomingQueryParams = Object.keys(req.query).length > 0;
    if (hasIncomingQueryParams || !defaultColumnsSearch) {
        return undefined;
    }
    // Filters: saved defaults override interactive default
    const filtersToApply = savedInteractiveDefaultsSearch && savedInteractiveDefaultsSearch.length
        ? savedInteractiveDefaultsSearch
        : defaultFiltersSearch;
    // Sort precedence: requested > default > none
    const sortToApply = requestedSort ?? defaultSort;
    // Build the query string progressively
    let query = defaultColumnsSearch;
    if (filtersToApply) {
        query = urlHelper.joinQueryStrings(query, filtersToApply);
    }
    if (sortToApply) {
        query = urlHelper.joinQueryStrings(query, sortToApply);
    }
    return query;
};
/**
 * Redirects the report to use the defaults
 *
 * @param {Response} res
 * @param {Request} req
 * @return {*}
 */
const redirectWithDefaults = (res, req) => {
    const finalQuery = createDefaultQueryString(req);
    if (finalQuery) {
        const baseUrl = req.originalUrl.split('?')[0].replace(/\/$/, '');
        res.redirect(`${baseUrl}?${finalQuery}`);
        return true;
    }
    return false;
};
/**
 * Updates the report state to expired and redirects
 *
 * @param {Request} req
 * @param {Response} res
 * @param {Services} services
 */
const updateStateToExpiredAndRedirect = async (req, res, services) => {
    const { tableId } = req.params;
    const { dprUser } = localsHelper.default.getValues(res);
    // set the report to expired
    await services.recentlyViewedService.setToExpiredByTableId(tableId, dprUser.id);
    await services.requestedReportService.setToExpiredByTableId(tableId, dprUser.id);
    // get the updated report state
    const updatedReportState = await services.recentlyViewedService.getReportByTableId(tableId, dprUser.id);
    const pollingUrl = updatedReportState?.url?.polling?.fullUrl;
    // redirect to polling page, or safe fallback
    res.redirect(pollingUrl ?? '/');
};
/**
 * Updates the state for a viewed ASYNC report
 *
 * @param {Request} req
 * @param {Services} services
 * @param {RequestedReport} reportStateData
 * @param {string} userId
 * @param {components['schemas']['FieldDefinition'][]} fields
 */
const updateLastViewedAsync = async (req, services, reportStateData, userId, fields) => {
    const { type, reportId, reportName, description, id, name, executionId, tableId, query, url } = reportStateData;
    const reportData = { type, reportId, reportName, description, id, name };
    const executionData = { executionId, tableId };
    const queryData = query ? { query: query.data, querySummary: query.summary } : { query: {}, querySummary: [] };
    const filtersQuery = queryMappers.extractFiltersFromQuery(req.query);
    const interactiveQueryData = {
        query: req.query,
        querySummary: utils.buildQuerySummary(filtersQuery, fields),
    };
    const recentlyViewedData = new UserStoreItemBuilder.UserStoreItemBuilder(reportData)
        .addExecutionData(executionData)
        .addQuery(queryData)
        .addInteractiveQuery(interactiveQueryData)
        .addStatus(types.RequestStatus.READY)
        .addTimestamp()
        .addAsyncUrls(url)
        .addReportUrls(req)
        .build();
    if (executionId)
        await services.requestedReportService.updateLastViewed(executionId, userId);
    await services.recentlyViewedService.setRecentlyViewed(recentlyViewedData, userId);
};
/**
 * Updates the last viewed state for a sync report
 *
 * @param {Request} req
 * @param {Services} services
 * @param {*} stateData
 * @param {string} userId
 * @param {components['schemas']['FieldDefinition'][]} fields
 */
const updateLastViewedSync = async (req, services, stateData, userId, fields) => {
    const filtersQuery = queryMappers.extractFiltersFromQuery(req.query);
    const interactiveQueryData = {
        query: req.query,
        querySummary: utils.buildQuerySummary(filtersQuery, fields),
    };
    const recentlyViewedData = new UserStoreItemBuilder.UserStoreItemBuilder(stateData)
        .addInteractiveQuery(interactiveQueryData)
        .addStatus(types.RequestStatus.READY)
        .addTimestamp()
        .addReportUrls(req)
        .build();
    await services.recentlyViewedService?.setRecentlyViewed(recentlyViewedData, userId);
};
var ViewReportUtils = {
    applyDashboardInteractiveQuery,
    applyReportInteractiveQuery,
    resetFilters,
    resetFiltersQueryString,
    resetColumnsQueryString,
    redirectWithDefaults,
};

exports.applyDashboardInteractiveQuery = applyDashboardInteractiveQuery;
exports.applyReportInteractiveQuery = applyReportInteractiveQuery;
exports.default = ViewReportUtils;
exports.updateLastViewedAsync = updateLastViewedAsync;
exports.updateLastViewedSync = updateLastViewedSync;
exports.updateStateToExpiredAndRedirect = updateStateToExpiredAndRedirect;
//# sourceMappingURL=utils.js.map
