"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.convertMetricFilterToDbt = void 0;
const tslib_1 = require("tslib");
const assertUnreachable_1 = tslib_1.__importDefault(require("../utils/assertUnreachable"));
const errors_1 = require("./errors");
const filter_1 = require("./filter");
const filterGrammar_1 = tslib_1.__importDefault(require("./filterGrammar"));
const isValidMetricFilterRule = (filter) => {
    const { values, operator } = filter;
    const operatorAllowsEmptyValues = [
        filter_1.FilterOperator.NULL,
        filter_1.FilterOperator.NOT_NULL,
    ].includes(operator);
    const firstValue = values?.[0];
    return operatorAllowsEmptyValues || firstValue !== undefined;
};
/**
 * Converts a filter rule from custom metrics to dbt meta tags in yml
 * More info about dbt filters: https://docs.lightdash.com/references/metrics/#available-filter-types
 */
const convertFilterOperatorToDbt = (filter) => {
    const { values, operator } = filter;
    if (!isValidMetricFilterRule(filter)) {
        throw new errors_1.ParameterError(`Filter values are undefined for filter: ${JSON.stringify(filter)}`);
    }
    // Operators without values are handled here
    switch (operator) {
        case filter_1.FilterOperator.NULL:
            return [`null`];
        case filter_1.FilterOperator.NOT_NULL:
            return [`!null`];
        default:
            break; // continue
    }
    const validValues = values;
    const firstValue = validValues[0];
    switch (operator) {
        case filter_1.FilterOperator.EQUALS:
            return validValues?.map((value) => `${value}`);
        case filter_1.FilterOperator.NOT_EQUALS:
            return [`!${firstValue}`];
        case filter_1.FilterOperator.INCLUDE:
            return [`%${firstValue}%`];
        case filter_1.FilterOperator.NOT_INCLUDE:
            return [`!%${firstValue}%`];
        case filter_1.FilterOperator.STARTS_WITH:
            return [`${firstValue}%`];
        case filter_1.FilterOperator.ENDS_WITH:
            return [`%${firstValue}`];
        case filter_1.FilterOperator.GREATER_THAN:
            return [`> ${firstValue}`];
        case filter_1.FilterOperator.GREATER_THAN_OR_EQUAL:
            return [`>= ${firstValue}`];
        case filter_1.FilterOperator.LESS_THAN:
            return [`< ${firstValue}`];
        case filter_1.FilterOperator.LESS_THAN_OR_EQUAL:
            return [`<= ${firstValue}`];
        case filter_1.FilterOperator.IN_THE_NEXT:
        case filter_1.FilterOperator.IN_THE_PAST:
            if ((0, filter_1.isDateFilterRule)(filter)) {
                const settings = filter.settings;
                const unitOfTime = settings.unitOfTime || filter_1.UnitOfTime.days;
                if (settings.completed) {
                    throw new errors_1.NotImplementedError('Custom metric completed filter is not supported on dbt');
                }
                return [`${operator} ${firstValue} ${unitOfTime}`];
            }
            throw new errors_1.NotImplementedError(`No function implemented to convert date custom metric filter to dbt: ${operator}`);
        case filter_1.FilterOperator.IN_THE_CURRENT:
        case filter_1.FilterOperator.IN_BETWEEN:
        case filter_1.FilterOperator.NOT_IN_THE_PAST:
        case filter_1.FilterOperator.NOT_IN_THE_CURRENT:
        case filter_1.FilterOperator.NOT_IN_BETWEEN:
        case filter_1.FilterOperator.IN_PERIOD_TO_DATE:
            throw new errors_1.NotImplementedError(`No function implemented to convert custom metric filter to dbt: ${operator}`);
        default:
            (0, assertUnreachable_1.default)(operator, `No function implemented to convert custom metric filter to dbt: ${operator}`);
    }
    return [];
};
const convertMetricFilterToDbt = (filters) => {
    if (!filters)
        return undefined;
    return filters.reduce((acc, filter) => {
        const { target } = filter;
        if (!isValidMetricFilterRule(filter))
            return acc;
        const values = convertFilterOperatorToDbt(filter);
        const fieldRefParts = target.fieldRef.split('.');
        const fieldId = fieldRefParts.length > 1 ? fieldRefParts[1] : target.fieldRef;
        const dbtFilters = {
            [fieldId]: values.length > 1 ? values : values[0],
        };
        return [...(acc || []), dbtFilters];
    }, []);
};
exports.convertMetricFilterToDbt = convertMetricFilterToDbt;
exports.default = filterGrammar_1.default;
//# sourceMappingURL=filterGrammarConversion.js.map