import { FilterType } from './filter-input/enum.js';
import SelectedFiltersUtils from './filters-selected/utils.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 { FiltersType } from './filtersTypeEnum.js';
import localsHelper from '../../utils/localsHelper.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;
};
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;
};
const setRequestQueryFromFilterValues = (filterValues, verbose = false) => {
    const requestQuery = filterValues
        .filter((fv) => fv.value)
        .reduce((acc, curr) => {
        const { value, name, type } = curr;
        const filterPrefix = `filters.${name}`;
        switch (type) {
            case FilterType.granularDateRange.toLowerCase():
                {
                    const granularDateRangeValue = value;
                    Object.keys(granularDateRangeValue).forEach((key) => {
                        let v = granularDateRangeValue[key];
                        if (key.includes('partialDate')) {
                            acc = {
                                ...acc,
                            };
                        }
                        else {
                            if (key.includes('granularity') || key.includes('quickFilter')) {
                                v = v.value;
                            }
                            acc = {
                                ...acc,
                                [`${filterPrefix}.${key}`]: v,
                            };
                        }
                    });
                }
                break;
            case FilterType.dateRange.toLowerCase():
                if (value) {
                    Object.keys(value).forEach((key) => {
                        const attrKey = !verbose && key.includes('relative') ? undefined : `${filterPrefix}.${key}`;
                        const attrValue = value[key];
                        if (attrKey) {
                            acc = {
                                ...acc,
                                [`${attrKey}`]: attrValue,
                            };
                        }
                    });
                }
                break;
            case FilterType.multiselect.toLowerCase():
                acc = {
                    ...acc,
                    [`${filterPrefix}`]: value.split(','),
                };
                break;
            default:
                acc = {
                    ...acc,
                    [`${filterPrefix}`]: value,
                };
                break;
        }
        return acc;
    }, {});
    return requestQuery;
};
const getPersonalisedFilters = async (filters, req, res, services, filtersType) => {
    const { reportId, id } = req.params;
    const { dprUser } = localsHelper.getValues(res);
    const defaultFilterValues = await services.defaultFilterValuesService.get(dprUser.id, reportId, id, filtersType);
    let defaultFilters = filters;
    if (defaultFilterValues) {
        const personalisedFilters = PersonalisationUtils.setFilterValuesFromSavedDefaults(filters, [], defaultFilterValues);
        defaultFilters = personalisedFilters.filters;
    }
    return { filters: defaultFilters, defaultFilterValues };
};
const getFilters = async ({ fields, req, res, prefix = 'filters.', services, filtersType, }) => {
    // 1. Set the filters from the product definition
    let filters = await getFiltersFromDefinition(fields, filtersType === FiltersType.INTERACTIVE);
    let hasDefaults;
    let canSaveDefaults = false;
    if (services && res && res.locals['saveDefaultsEnabled']) {
        // 2. If there are personalised filters, overwrite fiters with the personalised filter values.
        const { filters: personalisedFilterValues, defaultFilterValues } = await getPersonalisedFilters(filters, req, res, services, filtersType);
        filters = personalisedFilterValues;
        hasDefaults = defaultFilterValues && defaultFilterValues.length > 0;
        canSaveDefaults = true;
    }
    // If there is a request query, overwrite the filters with the query params
    if (req.query) {
        filters = setFilterValuesFromRequest(filters, req);
    }
    // Set the selected filters
    const selectedFilters = SelectedFiltersUtils.getSelectedFilters(filters, prefix);
    return {
        filters,
        selectedFilters,
        hasDefaults,
        canSaveDefaults,
    };
};
var FiltersUtils = {
    getFiltersFromDefinition,
    setFilterValuesFromRequest,
    getFilters,
    setRequestQueryFromFilterValues,
    getPersonalisedFilters,
};

export { FiltersUtils as default, getFilters, getFiltersFromDefinition, getPersonalisedFilters, setFilterValuesFromRequest, setRequestQueryFromFilterValues };
//# sourceMappingURL=utils.js.map
