import { getFields, getDashboardFields, getFieldsWithFilters } from '../utils/definitionUtils.js';
import { buildFilterSchemaFromFields } from './buildFilterSchema.js';
import { extractFiltersFromBody, formBodyToQs } from '../utils/queryMappers.js';
import { joinQueryStrings } from '../utils/urlHelper.js';
import { getActiveJourneyValue } from '../utils/sessionHelper.js';
import { ReportType, LoadType } from '../types/UserReports.js';

/**
 * Middleware to validate a report or dashboard filter request
 *
 * - creates a schema dynamically from the filter definitions
 * - checks the form data against it
 * - sets errors in req.flash if there are errors
 * - and redirects back to current page
 *
 * @param {*} req
 * @param {*} res
 * @param {*} next
 * @return {*}
 */
const validateFilters = ({ interactive, loadType = LoadType.ASYNC }) => (req, res, next) => {
    const { type: reportType } = req.params;
    const definition = res.locals.definition;
    if (!definition) {
        next(new Error('Definition missing from res.locals'));
    }
    else {
        // Normalise the filters
        const rawBody = req.body;
        const normalisedFilters = rawBody && typeof rawBody === 'object' ? extractFiltersFromBody(rawBody) : {};
        // Get the fields
        const fields = reportType === ReportType.REPORT
            ? getFields(definition)
            : getDashboardFields(definition);
        // Get only the relevant applicable fields for the form type
        const applicableFields = getFieldsWithFilters(fields).filter((field) => {
            const isInteractive = field.filter?.interactive === true;
            return interactive ? isInteractive : !isInteractive;
        });
        // Build the schema based on the fields filters and check it
        const schema = buildFilterSchemaFromFields(applicableFields);
        const result = schema.safeParse(normalisedFilters);
        if (result.success) {
            // All good - go to request the report middleware
            res.locals.validatedFilters = result.data;
            next();
        }
        else {
            const errors = result.error.issues.map((issue) => ({
                href: `#filters.${issue.path.join('.')}`,
                text: issue.message,
            }));
            req.flash('DPR_ERRORS', JSON.stringify(errors));
            let redirect = req.originalUrl;
            if (interactive) {
                const currentParams = buildRedirectParams(req, rawBody, loadType);
                redirect = `${req.baseUrl}?${currentParams}`;
            }
            res.redirect(redirect);
        }
    }
};
/**
 * Builds the redirect params from the form body
 * - used for interactive report filters
 *
 * @param {Request} req
 * @param {Record<string, unknown>} rawBody
 * @param {LoadType} loadType
 * @return {*}
 */
const buildRedirectParams = (req, rawBody, loadType) => {
    const { tableId, id, reportId } = req.params;
    // Create the qs from the form body
    const filtersQs = formBodyToQs(rawBody);
    // Get the current query string params
    const sessionKey = loadType === LoadType.ASYNC ? { id, tableId, reportId } : { id, reportId };
    const currentColumnsSearch = getActiveJourneyValue(req, sessionKey, 'currentReportColumnsSearch');
    const currentSortSearch = getActiveJourneyValue(req, sessionKey, 'currentSortSearch');
    const currentPageSizeSearch = getActiveJourneyValue(req, sessionKey, 'currentPageSizeSearch');
    return joinQueryStrings(filtersQs, currentColumnsSearch, currentSortSearch, currentPageSizeSearch, 'preventDefault=true');
};

export { validateFilters };
//# sourceMappingURL=validateFilters.js.map
