import { buildJourneyKey } from '../utils/sessionHelper.js';
import { setNestedPath } from '../utils/urlHelper.js';
import { qsToQueryObject, queryObjectToQs } from '../utils/queryMappers.js';
import { LoadType } from '../types/UserReports.js';
import localsHelper from '../utils/localsHelper.js';
import { getDefinitionByType, getDefaultFiltersQueryString, getDefaultColumnsQueryString, getDefaultSortQueryString } from '../utils/definitionUtils.js';
import { FiltersType } from '../components/_filters/filtersTypeEnum.js';
import { createQsFromSavedDefaults } from '../utils/Personalisation/personalisationUtils.js';

const storeActiveReportSessionData = ({ services, loadType = LoadType.ASYNC }) => async (req, res, next) => {
    if (!req.session) {
        return next(new Error('Session not initialized'));
    }
    if (req.method !== 'GET') {
        return next();
    }
    // --- Initialise Session Namespace -------------------------------------
    if (!req.session.activeReport) {
        req.session.activeReport = {};
    }
    const store = req.session.activeReport;
    // --- Build Key Variants & Data configurataions -------------------------
    const { baseKey, execKey, tableKey } = buildKeyVariants(req);
    const { baseData, execData, tableData } = await buildDataConfiguration(req, res, services, loadType);
    // --- Write Base Key (always updated) ----------------------------------
    store[baseKey] = {
        ...(store[baseKey] ?? {}),
        ...baseData,
    };
    // --- Write Exec Key (async loading) -----------------------------------
    if (execKey && execData) {
        store[execKey] = {
            ...(store[execKey] ?? {}),
            ...execData,
        };
    }
    // --- Write Table Key (final async state) ------------------------------
    if (tableKey && tableData) {
        store[tableKey] = {
            ...(store[tableKey] ?? {}),
            ...tableData,
        };
    }
    return next();
};
/**
 * Creates the active report data configuration
 *
 * @param {Request} req
 * @param {Response} res
 * @param {Services} services
 * @return {*}
 */
const buildDataConfiguration = async (req, res, services, loadType) => {
    // Normalise Express params (string | string[])
    const asString = (v) => (Array.isArray(v) ? v[0] : v);
    const p = req.params;
    // -------------- Get static values -------------------
    // - values that dont change during the active report journey
    const id = asString(p['id']);
    const reportId = asString(p['reportId']);
    const executionId = asString(p['executionId']);
    const tableId = asString(p['tableId']);
    const reportType = asString(p['type']);
    const { definitionsPath, dprUser } = localsHelper.getValues(res);
    const { token } = dprUser;
    const { fields } = await getDefinitionByType(reportType, services, token, reportId, id, definitionsPath);
    const definitionDefaults = await setUpDefaultsFromDefinition(fields);
    // -------------- Fetch Dynamic Values -------------------
    // values that are subject to change during the journey
    const reportIsBookmarked = await setUpBookmark(req, res, services.bookmarkService);
    const downloadEnabled = await setUpDownloadConfig(req, res, services.downloadPermissionService);
    const feedbackSubmissionFormPath = setupDownloadFeedbackPaths(req, res);
    const reportUrls = setUpReportUrls(req);
    const savedDefaults = await setupSavedDefaults(req, res, services.defaultFilterValuesService, fields);
    // -------------- Prepare Data Payloads -------------------
    const baseData = {
        id,
        reportId,
        reportIsBookmarked,
        downloadEnabled,
        loadType,
        ...definitionDefaults,
        ...savedDefaults,
    };
    // Sync: these values never change → store them under baseKey
    if (loadType === LoadType.SYNC) {
        Object.assign(baseData, {
            feedbackSubmissionFormPath,
            ...reportUrls,
        });
    }
    const execData = executionId ? { executionId } : undefined;
    const tableData = tableId
        ? {
            tableId,
            ...(executionId && { executionId }),
            ...(feedbackSubmissionFormPath && { feedbackSubmissionFormPath }),
            ...reportUrls,
        }
        : undefined;
    return {
        baseData,
        execData,
        tableData,
    };
};
/**
 * initialises the active report keys
 *
 * @param {Request} req
 * @return {*}
 */
const buildKeyVariants = (req) => {
    const { id, reportId } = req.params;
    const { executionId, tableId } = req.params;
    const baseKey = buildJourneyKey({ reportId, id });
    const execKey = executionId ? buildJourneyKey({ reportId, id, executionId }) : undefined;
    const tableKey = tableId ? buildJourneyKey({ reportId, id, tableId }) : undefined;
    return {
        baseKey,
        execKey,
        tableKey,
    };
};
/**
 * Sets up the active report journey URLS
 *
 * @param {Request} req
 * @return {*}
 */
const setUpReportUrls = (req) => {
    let currentReportPathname;
    let currentReportSearch;
    let currentReportUrl;
    let currentReportFiltersSearch;
    let currentReportColumnsSearch;
    let currentPageSizeSearch;
    let currentSortSearch;
    if (req.originalUrl.includes('view-report')) {
        const url = new URL(req.originalUrl, `${req.protocol}://${req.get('host')}`);
        currentReportPathname = url.pathname;
        currentReportSearch = url.search;
        currentReportUrl = req.originalUrl;
    }
    if (currentReportSearch !== undefined) {
        // Create the current filters string
        const filterQueryObject = qsToQueryObject(currentReportSearch, 'filters.');
        currentReportFiltersSearch = queryObjectToQs(filterQueryObject);
        // Create the current columns string
        const columnsQueryObject = qsToQueryObject(currentReportSearch, 'columns');
        currentReportColumnsSearch = queryObjectToQs(columnsQueryObject);
        // Create the current paging string
        const pageSizeQueryObject = qsToQueryObject(currentReportSearch, 'pageSize');
        currentPageSizeSearch = queryObjectToQs(pageSizeQueryObject);
        // Create the current sort string
        const pageSortQueryObject = qsToQueryObject(currentReportSearch, 'sort');
        currentSortSearch = queryObjectToQs(pageSortQueryObject);
    }
    return {
        ...(currentReportPathname && { currentReportPathname }),
        ...(currentReportSearch !== undefined && { currentReportSearch }),
        ...(currentReportUrl && { currentReportUrl }),
        ...(currentReportFiltersSearch !== undefined && { currentReportFiltersSearch }),
        ...(currentReportColumnsSearch !== undefined && { currentReportColumnsSearch }),
        ...(currentPageSizeSearch !== undefined && { currentPageSizeSearch }),
        ...(currentSortSearch !== undefined && { currentSortSearch }),
    };
};
/**
 * Sets up the default query strings from the definition
 *
 * @param {Request} req
 * @param {Response} res
 * @param {ReportingService} service
 * @return {*}
 */
const setUpDefaultsFromDefinition = async (fields) => {
    const filtersQueryStrings = getDefaultFiltersQueryString(fields);
    const defaultColumnsSearch = getDefaultColumnsQueryString(fields);
    const defaultSortQueryString = getDefaultSortQueryString(fields);
    return {
        ...filtersQueryStrings,
        defaultColumnsSearch,
        defaultSortQueryString,
    };
};
/**
 * Sets up the bookmark configuration for the active report
 *
 * @param {Request} req
 * @param {Response} res
 * @param {BookmarkService} service
 * @return {*}
 */
const setUpBookmark = async (req, res, service) => {
    const { reportId, id } = req.params;
    const userId = res.locals['dprUser'].id;
    let reportIsBookmarked = false;
    if (reportId && id && userId) {
        reportIsBookmarked = (await service.isBookmarked(id, reportId, userId)) || false;
    }
    return reportIsBookmarked;
};
/**
 * Sets up the download configuration for the active report
 *
 * @param {Request} req
 * @param {Response} res
 * @param {DownloadPermissionService} service
 * @return {*}
 */
const setUpDownloadConfig = async (req, res, service) => {
    const { reportId, id } = req.params;
    const userId = res.locals['dprUser'].id;
    let downloadEnabled = false;
    if (reportId && id && userId) {
        downloadEnabled = await service.downloadEnabledForReport(userId, reportId, id);
    }
    return downloadEnabled;
};
/**
 * Sets up the feedback configuration for the active report
 *
 * @param {Request} req
 * @param {Response} res
 * @return {*}
 */
const setupDownloadFeedbackPaths = (req, res) => {
    const { reportId, id, tableId } = req.params;
    const { nestedBaseUrl } = localsHelper.getRouteLocals(res);
    let feedbackSubmissionFormPath;
    if (reportId && id) {
        feedbackSubmissionFormPath = tableId
            ? `/dpr/download-report/request-download/${reportId}/${id}/tableId/${tableId}/form`
            : `/dpr/download-report/request-download/${reportId}/${id}/form`;
        feedbackSubmissionFormPath = setNestedPath(feedbackSubmissionFormPath, nestedBaseUrl);
    }
    return feedbackSubmissionFormPath;
};
/**
 * Sets up the saved defaults as query strings
 *
 * @param {Request} req
 * @param {Response} res
 * @param {DefaultFilterValuesService} service
 * @return {*}
 */
const setupSavedDefaults = async (req, res, service, fields) => {
    const { reportId, id } = req.params;
    const userId = res.locals['dprUser'].id;
    const savedRequestFilterValues = await service.get(userId, reportId, id, FiltersType.REQUEST);
    const savedInteractiveFilterValues = await service.get(userId, reportId, id, FiltersType.INTERACTIVE);
    const savedRequestDefaultsSearch = savedRequestFilterValues && savedRequestFilterValues.length
        ? createQsFromSavedDefaults(savedRequestFilterValues, fields)
        : '';
    const savedInteractiveDefaultsSearch = savedInteractiveFilterValues && savedInteractiveFilterValues.length
        ? createQsFromSavedDefaults(savedInteractiveFilterValues, fields)
        : '';
    return {
        savedRequestDefaultsSearch,
        savedInteractiveDefaultsSearch,
    };
};

export { buildKeyVariants, storeActiveReportSessionData };
//# sourceMappingURL=setUpActiveReport.js.map
