"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const cloneDeep_1 = tslib_1.__importDefault(require("lodash/cloneDeep"));
const field_1 = require("./field");
const filter_1 = require("./filter");
describe('applyDimensionOverrides', () => {
    // Test fixtures
    const createBaseDashboardFilter = (id, fieldId, tableName, values = ['value1'], tileTargets = {}) => ({
        id,
        label: `Label for ${fieldId}`,
        operator: filter_1.FilterOperator.EQUALS,
        target: {
            fieldId,
            tableName,
        },
        tileTargets,
        disabled: false,
        values,
    });
    const createOverrideFilter = (id, fieldId, tableName, values = ['overrideValue'], operator = filter_1.FilterOperator.EQUALS) => ({
        id,
        label: `Override for ${fieldId}`,
        operator,
        target: {
            fieldId,
            tableName,
        },
        disabled: false,
        values,
    });
    const baseDashboardFilters = {
        dimensions: [
            createBaseDashboardFilter('filter-1', 'customers_customer_id', 'customers', ['123', '456'], {
                'tile-1': {
                    fieldId: 'customers_customer_id',
                    tableName: 'customers',
                },
                'tile-2': false,
            }),
            createBaseDashboardFilter('filter-2', 'orders_status', 'orders', ['completed'], {
                'tile-1': {
                    fieldId: 'orders_status',
                    tableName: 'orders',
                },
            }),
        ],
        metrics: [],
        tableCalculations: [],
    };
    describe('when overrides is an array of DashboardFilterRule[]', () => {
        it('should apply overrides to existing dimensions while preserving tileTargets', () => {
            const overrides = [
                createOverrideFilter('filter-1', 'customers_customer_id', 'customers', ['789'], // different values
                filter_1.FilterOperator.IN_BETWEEN),
            ];
            const result = (0, filter_1.applyDimensionOverrides)(baseDashboardFilters, overrides);
            expect(result).toHaveLength(2);
            expect(result[0]).toEqual({
                id: 'filter-1',
                label: 'Override for customers_customer_id',
                operator: filter_1.FilterOperator.IN_BETWEEN,
                target: {
                    fieldId: 'customers_customer_id',
                    tableName: 'customers',
                },
                disabled: false,
                values: ['789'],
                // tileTargets should be preserved from original
                tileTargets: {
                    'tile-1': {
                        fieldId: 'customers_customer_id',
                        tableName: 'customers',
                    },
                    'tile-2': false,
                },
            });
            // Second filter should remain unchanged
            expect(result[1]).toEqual(baseDashboardFilters.dimensions[1]);
        });
        it('should add new dimensions that do not exist in dashboard filters', () => {
            const overrides = [
                createOverrideFilter('filter-3', 'products_category', 'products', ['electronics']),
                createOverrideFilter('filter-4', 'users_age', 'users', ['25'], filter_1.FilterOperator.GREATER_THAN),
            ];
            const result = (0, filter_1.applyDimensionOverrides)(baseDashboardFilters, overrides);
            expect(result).toHaveLength(4);
            // Original filters should remain
            expect(result.slice(0, 2)).toEqual(baseDashboardFilters.dimensions);
            // New filters should be added
            expect(result[2]).toEqual(overrides[0]);
            expect(result[3]).toEqual(overrides[1]);
        });
        it('should handle mixed scenario: override existing and add new', () => {
            const overrides = [
                createOverrideFilter('filter-1', 'customers_customer_id', 'customers', ['999'], filter_1.FilterOperator.NOT_EQUALS),
                createOverrideFilter('filter-3', 'new_field', 'new_table', [
                    'new_value',
                ]),
            ];
            const result = (0, filter_1.applyDimensionOverrides)(baseDashboardFilters, overrides);
            expect(result).toHaveLength(3);
            // First filter should be overridden
            expect(result[0].values).toEqual(['999']);
            expect(result[0].operator).toBe(filter_1.FilterOperator.NOT_EQUALS);
            expect(result[0].tileTargets).toEqual(baseDashboardFilters.dimensions[0].tileTargets);
            // Second filter should remain unchanged
            expect(result[1]).toEqual(baseDashboardFilters.dimensions[1]);
            // Third filter should be new
            expect(result[2]).toEqual(overrides[1]);
        });
        it('should handle empty overrides array', () => {
            const overrides = [];
            const result = (0, filter_1.applyDimensionOverrides)(baseDashboardFilters, overrides);
            expect(result).toEqual(baseDashboardFilters.dimensions);
        });
        it('should handle overrides with complex tileTargets', () => {
            const complexTileTargets = {
                'tile-1': {
                    fieldId: 'mapped_field',
                    tableName: 'mapped_table',
                    isSqlColumn: true,
                },
                'tile-2': false,
                'tile-3': {
                    fieldId: 'another_field',
                    tableName: 'another_table',
                    fallbackType: field_1.DimensionType.STRING,
                },
            };
            const dashboardWithComplexTileTargets = {
                ...baseDashboardFilters,
                dimensions: [
                    createBaseDashboardFilter('complex-filter', 'complex_field', 'complex_table', ['value'], complexTileTargets),
                ],
            };
            const overrides = [
                createOverrideFilter('complex-filter', 'complex_field', 'complex_table', ['override_value']),
            ];
            const result = (0, filter_1.applyDimensionOverrides)(dashboardWithComplexTileTargets, overrides);
            expect(result[0].tileTargets).toEqual(complexTileTargets);
            expect(result[0].values).toEqual(['override_value']);
        });
    });
    describe('when overrides is a DashboardFilters object', () => {
        it('should use dimensions array from DashboardFilters', () => {
            const overrides = {
                dimensions: [
                    createOverrideFilter('filter-1', 'customers_customer_id', 'customers', ['override_from_object']),
                ],
                metrics: [
                    // These should be ignored when applying dimension overrides
                    createOverrideFilter('metric-1', 'revenue', 'orders', [
                        '1000',
                    ]),
                ],
                tableCalculations: [],
            };
            const result = (0, filter_1.applyDimensionOverrides)(baseDashboardFilters, overrides);
            expect(result).toHaveLength(2);
            expect(result[0].values).toEqual(['override_from_object']);
            expect(result[0].tileTargets).toEqual(baseDashboardFilters.dimensions[0].tileTargets);
            // Second filter should remain unchanged
            expect(result[1]).toEqual(baseDashboardFilters.dimensions[1]);
        });
        it('should work with empty dimensions array in DashboardFilters', () => {
            const overrides = {
                dimensions: [],
                metrics: [],
                tableCalculations: [],
            };
            const result = (0, filter_1.applyDimensionOverrides)(baseDashboardFilters, overrides);
            expect(result).toEqual(baseDashboardFilters.dimensions);
        });
    });
    describe('edge cases', () => {
        it('should handle empty dashboard dimensions', () => {
            const emptyDashboard = {
                dimensions: [],
                metrics: [],
                tableCalculations: [],
            };
            const overrides = [
                createOverrideFilter('new-filter', 'field', 'table'),
            ];
            const result = (0, filter_1.applyDimensionOverrides)(emptyDashboard, overrides);
            expect(result).toEqual(overrides);
        });
        it('should handle filters with same id but different field properties', () => {
            const overrides = [
                {
                    ...createOverrideFilter('filter-1', 'customers_customer_id', 'customers'),
                    label: 'Completely different label',
                    disabled: true,
                    required: true,
                    singleValue: true,
                    settings: { someCustomSetting: 'value' },
                },
            ];
            const result = (0, filter_1.applyDimensionOverrides)(baseDashboardFilters, overrides);
            expect(result[0]).toEqual({
                ...overrides[0],
                tileTargets: baseDashboardFilters.dimensions[0].tileTargets,
                // Requirement flags are owned by the saved dashboard
                required: undefined,
            });
        });
        it('should not modify original dashboard filters', () => {
            const originalFilters = (0, cloneDeep_1.default)(baseDashboardFilters);
            const overrides = [
                createOverrideFilter('filter-1', 'customers_customer_id', 'customers'),
            ];
            (0, filter_1.applyDimensionOverrides)(baseDashboardFilters, overrides);
            expect(baseDashboardFilters).toEqual(originalFilters);
        });
        it('should handle filters with different operator types', () => {
            const overrides = [
                {
                    ...createOverrideFilter('filter-1', 'customers_customer_id', 'customers'),
                    operator: filter_1.FilterOperator.NULL,
                    values: undefined, // NULL operator doesn't need values
                },
                {
                    ...createOverrideFilter('filter-5', 'date_field', 'events'),
                    operator: filter_1.FilterOperator.IN_THE_PAST,
                    values: [7], // number value for date operations
                    settings: {
                        unitOfTime: 'days',
                        completed: true,
                    },
                },
            ];
            const result = (0, filter_1.applyDimensionOverrides)(baseDashboardFilters, overrides);
            expect(result[0].operator).toBe(filter_1.FilterOperator.NULL);
            expect(result[0].values).toBeUndefined();
            expect(result[2].operator).toBe(filter_1.FilterOperator.IN_THE_PAST);
            expect(result[2].settings).toEqual({
                unitOfTime: 'days',
                completed: true,
            });
        });
        it('should preserve all properties from original tileTargets', () => {
            const complexDashboard = {
                dimensions: [
                    {
                        ...createBaseDashboardFilter('filter-1', 'field', 'table'),
                        tileTargets: {
                            'tile-1': {
                                fieldId: 'mapped_field',
                                tableName: 'mapped_table',
                                isSqlColumn: true,
                                fallbackType: field_1.DimensionType.NUMBER,
                            },
                        },
                    },
                ],
                metrics: [],
                tableCalculations: [],
            };
            const overrides = [
                createOverrideFilter('filter-1', 'field', 'table'),
            ];
            const result = (0, filter_1.applyDimensionOverrides)(complexDashboard, overrides);
            expect(result[0].tileTargets).toEqual({
                'tile-1': {
                    fieldId: 'mapped_field',
                    tableName: 'mapped_table',
                    isSqlColumn: true,
                    fallbackType: 'number',
                },
            });
        });
    });
    describe('real-world scenarios', () => {
        it('should handle scheduler filter overrides scenario', () => {
            // Simulating a scenario where scheduled reports override dashboard filters
            const schedulerOverrides = [
                {
                    id: 'filter-1',
                    label: 'Scheduled Customer Filter',
                    operator: filter_1.FilterOperator.EQUALS,
                    target: {
                        fieldId: 'customers_customer_id',
                        tableName: 'customers',
                    },
                    disabled: false,
                    values: ['scheduled_customer_123'],
                },
                {
                    id: 'scheduler-date-filter',
                    label: 'Last 30 Days',
                    operator: filter_1.FilterOperator.IN_THE_PAST,
                    target: {
                        fieldId: 'orders_created_date',
                        tableName: 'orders',
                    },
                    disabled: false,
                    values: [30],
                    settings: {
                        unitOfTime: 'days',
                        completed: true,
                    },
                },
            ];
            const result = (0, filter_1.applyDimensionOverrides)(baseDashboardFilters, schedulerOverrides);
            expect(result).toHaveLength(3);
            // Override should be applied
            expect(result[0].values).toEqual(['scheduled_customer_123']);
            expect(result[0].label).toBe('Scheduled Customer Filter');
            expect(result[0].tileTargets).toEqual(baseDashboardFilters.dimensions[0].tileTargets);
            // Original filter should remain
            expect(result[1]).toEqual(baseDashboardFilters.dimensions[1]);
            // New scheduler filter should be added
            expect(result[2]).toEqual(schedulerOverrides[1]);
        });
        it('should handle URL parameter override scenario', () => {
            // Simulating URL parameters overriding dashboard filters
            const urlOverrides = [
                {
                    id: 'filter-2',
                    label: 'Orders Status (from URL)',
                    operator: filter_1.FilterOperator.INCLUDE,
                    target: {
                        fieldId: 'orders_status',
                        tableName: 'orders',
                    },
                    disabled: false,
                    values: ['completed', 'shipped', 'delivered'],
                },
            ];
            const result = (0, filter_1.applyDimensionOverrides)(baseDashboardFilters, urlOverrides);
            expect(result).toHaveLength(2);
            expect(result[1].operator).toBe(filter_1.FilterOperator.INCLUDE);
            expect(result[1].values).toEqual([
                'completed',
                'shipped',
                'delivered',
            ]);
            expect(result[1].tileTargets).toEqual(baseDashboardFilters.dimensions[1].tileTargets);
        });
    });
    // A shared link carries a filter id that no longer matches the saved filter
    // (the id is regenerated when a filter is deleted and re-added or its field
    // is changed). The override must fall back to matching by fieldId +
    // tableName so it merges into the saved filter and inherits its tileTargets,
    // instead of being appended as a duplicate that applies to every tile.
    describe('field-match fallback for stale ids', () => {
        it('reconciles a stale id by field and inherits the saved tileTargets', () => {
            const savedFilters = {
                dimensions: [
                    createBaseDashboardFilter('new-id', 'customers_customer_id', 'customers', ['123'], {
                        'tile-1': {
                            fieldId: 'customers_customer_id',
                            tableName: 'customers',
                        },
                        'tile-2': false,
                    }),
                ],
                metrics: [],
                tableCalculations: [],
            };
            const overrides = [
                createOverrideFilter('old-id', 'customers_customer_id', 'customers', ['789']),
            ];
            const result = (0, filter_1.applyDimensionOverrides)(savedFilters, overrides);
            // Merged into the saved filter, not appended as a duplicate.
            expect(result).toHaveLength(1);
            expect(result[0].id).toBe('new-id');
            expect(result[0].values).toEqual(['789']);
            expect(result[0].tileTargets?.['tile-2']).toBe(false);
        });
        it('appends an override that matches no saved filter by id or field', () => {
            const savedFilters = {
                dimensions: [
                    createBaseDashboardFilter('filter-1', 'customers_customer_id', 'customers'),
                ],
                metrics: [],
                tableCalculations: [],
            };
            const overrides = [
                createOverrideFilter('stale', 'orders_status', 'orders', [
                    'completed',
                ]),
            ];
            const result = (0, filter_1.applyDimensionOverrides)(savedFilters, overrides);
            expect(result).toHaveLength(2);
            expect(result[1]).toEqual(overrides[0]);
        });
        it('does not reconcile an override targeting a different tableName', () => {
            const savedFilters = {
                dimensions: [
                    createBaseDashboardFilter('saved', 'status', 'orders'),
                ],
                metrics: [],
                tableCalculations: [],
            };
            const overrides = [
                createOverrideFilter('stale', 'status', 'returns', ['x']),
            ];
            const result = (0, filter_1.applyDimensionOverrides)(savedFilters, overrides);
            expect(result).toHaveLength(2);
            expect(result[0]).toEqual(savedFilters.dimensions[0]);
            expect(result[1]).toEqual(overrides[0]);
        });
        it('prefers an id match over a same-field stale override, which is appended', () => {
            const savedFilters = {
                dimensions: [
                    createBaseDashboardFilter('filter-1', 'status', 'orders', [
                        'orig',
                    ]),
                ],
                metrics: [],
                tableCalculations: [],
            };
            const overrides = [
                createOverrideFilter('filter-1', 'status', 'orders', [
                    'id-match',
                ]),
                createOverrideFilter('stale', 'status', 'orders', [
                    'field-match',
                ]),
            ];
            const result = (0, filter_1.applyDimensionOverrides)(savedFilters, overrides);
            expect(result).toHaveLength(2);
            expect(result[0].values).toEqual(['id-match']);
            expect(result[1]).toEqual(overrides[1]);
        });
        it('reconciles only the first of two saved filters sharing a field', () => {
            const savedFilters = {
                dimensions: [
                    createBaseDashboardFilter('saved-a', 'customers_customer_id', 'customers', ['1'], {
                        'tile-1': {
                            fieldId: 'customers_customer_id',
                            tableName: 'customers',
                        },
                    }),
                    createBaseDashboardFilter('saved-b', 'customers_customer_id', 'customers', ['2']),
                ],
                metrics: [],
                tableCalculations: [],
            };
            const overrides = [
                createOverrideFilter('stale', 'customers_customer_id', 'customers', ['99']),
            ];
            const result = (0, filter_1.applyDimensionOverrides)(savedFilters, overrides);
            expect(result).toHaveLength(2);
            expect(result[0].id).toBe('saved-a');
            expect(result[0].values).toEqual(['99']);
            expect(result[1].id).toBe('saved-b');
            expect(result[1].values).toEqual(['2']);
        });
        it('propagates the override disabled state when reconciling by field', () => {
            const savedFilters = {
                dimensions: [
                    createBaseDashboardFilter('saved', 'status', 'orders', [
                        'orig',
                    ]),
                ],
                metrics: [],
                tableCalculations: [],
            };
            const overrides = [
                {
                    ...createOverrideFilter('stale', 'status', 'orders', [
                        'new',
                    ]),
                    disabled: true,
                },
            ];
            const result = (0, filter_1.applyDimensionOverrides)(savedFilters, overrides);
            expect(result).toHaveLength(1);
            expect(result[0].disabled).toBe(true);
            expect(result[0].values).toEqual(['new']);
        });
    });
    // required / requiredGroupId are set by the dashboard editor; an override
    // (shared link, embed JWT, scheduler) must not be able to strip or inject
    // them.
    describe('requirement flags are saved-dashboard-owned', () => {
        it('keeps the saved requirement flags when an override omits them', () => {
            const savedFilters = {
                dimensions: [
                    {
                        ...createBaseDashboardFilter('filter-1', 'customers_customer_id', 'customers'),
                        required: true,
                    },
                    {
                        ...createBaseDashboardFilter('filter-2', 'orders_status', 'orders'),
                        requiredGroupId: 'group-1',
                    },
                ],
                metrics: [],
                tableCalculations: [],
            };
            const overrides = [
                createOverrideFilter('filter-1', 'customers_customer_id', 'customers', ['789']),
                // Field-matched override with a stale id
                createOverrideFilter('stale', 'orders_status', 'orders', [
                    'completed',
                ]),
            ];
            const result = (0, filter_1.applyDimensionOverrides)(savedFilters, overrides);
            expect(result).toHaveLength(2);
            expect(result[0].required).toBe(true);
            expect(result[0].values).toEqual(['789']);
            expect(result[1].requiredGroupId).toBe('group-1');
            expect(result[1].values).toEqual(['completed']);
        });
        it('ignores requirement flags supplied by the override', () => {
            const savedFilters = {
                dimensions: [
                    createBaseDashboardFilter('filter-1', 'customers_customer_id', 'customers'),
                ],
                metrics: [],
                tableCalculations: [],
            };
            const overrides = [
                {
                    ...createOverrideFilter('filter-1', 'customers_customer_id', 'customers'),
                    required: true,
                    requiredGroupId: 'injected-group',
                },
            ];
            const result = (0, filter_1.applyDimensionOverrides)(savedFilters, overrides);
            expect(result).toHaveLength(1);
            expect(result[0].required).toBeUndefined();
            expect(result[0].requiredGroupId).toBeUndefined();
        });
        it('strips requirement flags from appended overrides', () => {
            const savedFilters = {
                dimensions: [
                    {
                        ...createBaseDashboardFilter('filter-1', 'orders_status', 'orders'),
                        requiredGroupId: 'group-1',
                        disabled: true,
                    },
                ],
                metrics: [],
                tableCalculations: [],
            };
            // Matches no saved filter by id or field, so it gets appended
            const overrides = [
                {
                    ...createOverrideFilter('new-filter', 'customers_customer_id', 'customers', ['789']),
                    required: true,
                    requiredGroupId: 'group-1',
                },
            ];
            const result = (0, filter_1.applyDimensionOverrides)(savedFilters, overrides);
            expect(result).toHaveLength(2);
            expect(result[1].id).toBe('new-filter');
            expect(result[1].values).toEqual(['789']);
            expect(result[1].required).toBeUndefined();
            expect(result[1].requiredGroupId).toBeUndefined();
        });
    });
});
//# sourceMappingURL=applyDimensionOverrides.test.js.map