import { FilterType } from './filter-input/enum.js';
import DateRangeInputUtils from '../_inputs/date-range/utils.js';
import DateInputUtils from '../_inputs/date-input/utils.js';
import GranularDateRangeInputUtils from '../_inputs/granular-date-range/utils.js';
import AutocompleteUtils from '../_inputs/autocomplete-text-input/utils.js';
import MultiSelectUtils from '../_inputs/multi-select/utils.js';
import PersonalisationUtils from '../../utils/Personalisation/personalisationUtils.js';
import SortHelper from '../_async/async-filters-form/sortByTemplate.js';

/**
 * Given a FilterValue[], will update the values to match the req.query values if present
 *
 * @param {FilterValue[]} filters
 * @param {Request} req
 * @param {string} [prefix='filters.']
 * @return {*}  {FilterValue[]}
 */
const setFilterValuesFromRequest = (filters, req, prefix = 'filters.') => {
    const { preventDefault } = req.query;
    if (Object.keys(req.query).every((key) => !key.includes(prefix)) && !preventDefault) {
        return filters;
    }
    return filters.map((filter) => {
        let requestfilterValue;
        let requestfilterValues;
        let requestOptionValue;
        const type = filter.type.toLowerCase();
        switch (type) {
            case FilterType.dateRange.toLowerCase():
                requestfilterValue = DateRangeInputUtils.setValueFromRequest(filter, req, prefix);
                break;
            case FilterType.granularDateRange.toLowerCase():
                requestfilterValue = GranularDateRangeInputUtils.setValueFromRequest(filter, req, prefix);
                break;
            case FilterType.date.toLowerCase():
                requestfilterValue = DateInputUtils.setValueFromRequest(filter, req, prefix);
                break;
            case FilterType.multiselect.toLowerCase():
                ({ requestfilterValue, requestfilterValues } = MultiSelectUtils.setValueFromRequest(filter, req, prefix));
                break;
            case FilterType.autocomplete.toLowerCase(): {
                ({ requestfilterValue, requestOptionValue } = AutocompleteUtils.setValueFromRequest(filter, req, prefix));
                break;
            }
            default:
                requestfilterValue = req.query[`${prefix}${filter.name}`];
                break;
        }
        let value = null;
        if (requestfilterValue) {
            value = requestfilterValue;
        }
        else if (preventDefault) {
            value = '';
        }
        return {
            ...filter,
            value,
            ...(requestfilterValues && { values: requestfilterValues }),
            ...(requestOptionValue && { staticOptionNameValue: requestOptionValue }),
        };
    });
};
const getFiltersFromDefinition = (fields, interactive) => {
    const filters = fields
        .filter((f) => f.filter)
        .filter((f) => {
        if (interactive !== undefined) {
            if (f.filter?.interactive === undefined) {
                return !interactive;
            }
            return interactive === f.filter.interactive;
        }
        return true;
    })
        .map((f) => {
        const { display: text, name } = f;
        const filter = f.filter;
        const { type, staticOptions, dynamicOptions, defaultValue, mandatory, pattern, index } = filter;
        const options = staticOptions
            ? staticOptions.map((opt) => {
                return { value: opt.name, text: opt.display };
            })
            : [];
        let filterData = {
            text,
            name,
            type: type,
            value: defaultValue || null,
            mandatory: mandatory || false,
            minimumLength: dynamicOptions?.minimumLength,
            pattern,
            index,
        };
        const noFilterOption = {
            value: 'no-filter',
            text: 'None',
            disabled: false,
        };
        switch (type) {
            case FilterType.autocomplete.toLowerCase():
                filterData = {
                    ...filterData,
                    options,
                };
                break;
            case FilterType.radio:
                if (!mandatory)
                    options.unshift(noFilterOption);
                filterData = {
                    ...filterData,
                    options,
                };
                break;
            case FilterType.select: {
                if (!mandatory)
                    options.unshift(noFilterOption);
                options.unshift({
                    value: '',
                    text: 'Select your option',
                    disabled: true,
                    selected: true,
                });
                filterData = {
                    ...filterData,
                    options,
                };
                break;
            }
            case FilterType.multiselect.toLowerCase():
                filterData = {
                    ...filterData,
                    options,
                    values: defaultValue ? defaultValue.split(',') : [],
                };
                break;
            case FilterType.dateRange.toLowerCase():
                filterData = DateRangeInputUtils.getFilterFromDefinition(filter, filterData);
                break;
            case FilterType.date.toLowerCase():
                filterData = DateInputUtils.getFilterFromDefinition(filter, filterData);
                break;
            case FilterType.granularDateRange.toLocaleLowerCase(): {
                filterData = GranularDateRangeInputUtils.getFilterFromDefinition(filter, filterData);
                break;
            }
        }
        return filterData;
    });
    const orderedFilters = orderFilters(filters);
    return orderedFilters;
};
/**
 * Initialises the sortData from the definition
 */
const getSortByFromDefinition = (fields) => {
    const sortBy = SortHelper.sortByTemplate();
    const options = fields
        .filter((f) => f.sortable)
        .map((f) => {
        if (f.defaultsort)
            sortBy[0].value = f.name;
        const field = { value: f.name, text: f.display };
        sortBy[1].value = f.sortDirection ? `${f.sortDirection === 'asc'}` : 'true';
        return field;
    });
    if (options.length) {
        const sortWithOptions = sortBy[0];
        sortWithOptions.options = options;
        sortBy[0] = sortWithOptions;
        return sortBy;
    }
    return [];
};
const orderFilters = (filterValues) => {
    const noIndexFilters = filterValues.filter((f) => f.index === undefined);
    const indexFilters = filterValues.filter((f) => f.index !== undefined);
    indexFilters.forEach((f) => {
        if (f.index !== undefined)
            noIndexFilters.splice(f.index, 0, f);
    });
    return noIndexFilters;
};
/**
 * Gets the filters for an interactive report
 *
 * @param {{
 *   fields: components['schemas']['FieldDefinition'][]
 *   req: Request
 * }} {
 *   fields,
 *   req,
 * }
 * @return {*}
 */
const getInteractiveFilters = async ({ fields, req, }) => {
    // 1. Set the filters from the product definition
    let filters = await getFiltersFromDefinition(fields, true);
    // 2. Set values from request
    filters = setFilterValuesFromRequest(filters, req);
    return filters;
};
/**
 * Gets the filters for pre-request
 *
 * @param {Request} req
 * @param {Response} res
 * @param {components['schemas']['FieldDefinition'][]} fields
 * @return {*}  {(Promise<RenderFiltersReturnValue | undefined>)}
 */
const getRequestFilters = async (req, res, fields) => {
    if (!fields || !fields.length) {
        return undefined;
    }
    // 1. Get filters from definition with default values
    let filters = getFiltersFromDefinition(fields, false);
    // 2. Get the sort from the definition
    const sortBy = getSortByFromDefinition(fields);
    // 3. Update filter values with user context values. eg. establishmnent code
    filters = PersonalisationUtils.setUserContextDefaults(res, filters);
    // 4. Overwrite filter values with query param values
    filters = setFilterValuesFromRequest(filters, req);
    return {
        filters,
        sortBy,
    };
};
var FiltersUtils = {
    getFiltersFromDefinition,
    setFilterValuesFromRequest,
    getInteractiveFilters,
};

export { FiltersUtils as default, getFiltersFromDefinition, getInteractiveFilters, getRequestFilters, getSortByFromDefinition, setFilterValuesFromRequest };
//# sourceMappingURL=utils.js.map
