"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.tableCalcsSchema = void 0;
exports.convertAiTableCalcsSchemaToTableCalcs = convertAiTableCalcsSchemaToTableCalcs;
const tslib_1 = require("tslib");
const zod_1 = require("zod");
const field_1 = require("../../../../types/field");
const assertUnreachable_1 = tslib_1.__importDefault(require("../../../../utils/assertUnreachable"));
const tableCalcPercentChangeFromPrevious_1 = require("./tableCalcPercentChangeFromPrevious");
const tableCalcPercentOfColumnTotal_1 = require("./tableCalcPercentOfColumnTotal");
const tableCalcPercentOfPreviousValue_1 = require("./tableCalcPercentOfPreviousValue");
const tableCalcRankInColumn_1 = require("./tableCalcRankInColumn");
const tableCalcRunningTotal_1 = require("./tableCalcRunningTotal");
const tableCalcWindowFunction_1 = require("./tableCalcWindowFunction");
const tableCalcSchema = zod_1.z.discriminatedUnion('type', [
    tableCalcPercentChangeFromPrevious_1.tableCalcPercentChangeFromPreviousSchema,
    tableCalcPercentOfPreviousValue_1.tableCalcPercentOfPreviousValueSchema,
    tableCalcPercentOfColumnTotal_1.tableCalcPercentOfColumnTotalSchema,
    tableCalcRankInColumn_1.tableCalcRankInColumnSchema,
    tableCalcRunningTotal_1.tableCalcRunningTotalSchema,
    tableCalcWindowFunction_1.tableCalcWindowFunctionSchema,
]);
exports.tableCalcsSchema = zod_1.z.array(tableCalcSchema).nullable().describe(`
Table calculations perform row-by-row calculations on query results without collapsing rows. Similar to SQL window functions.

**Available Types:**
- Simple calculations: percent_change_from_previous, percent_of_previous_value, percent_of_column_total, rank_in_column, running_total
- Advanced window_function: Supports row_number, percent_rank, sum, avg, count, min, max with optional partitioning, ordering, and frame clauses

**Technical Requirements:**
- Appear as additional columns in query results
- Can be used in sorts and filters alongside dimensions/metrics
- Multiple calculations can be combined in a single query
- All fields referenced must exist in the query (dimensions, metrics, or other table calculations)
`);
function frameBoundaryStringToEnum(boundaryType) {
    switch (boundaryType) {
        case 'unbounded_preceding':
            return field_1.FrameBoundaryType.UNBOUNDED_PRECEDING;
        case 'preceding':
            return field_1.FrameBoundaryType.PRECEDING;
        case 'current_row':
            return field_1.FrameBoundaryType.CURRENT_ROW;
        case 'following':
            return field_1.FrameBoundaryType.FOLLOWING;
        case 'unbounded_following':
            return field_1.FrameBoundaryType.UNBOUNDED_FOLLOWING;
        default:
            return (0, assertUnreachable_1.default)(boundaryType, 'Unknown boundary type');
    }
}
function convertTableCalcSchemaToTableCalc(tableCalc) {
    const { type, name, displayName } = tableCalc;
    // Build the template
    const baseCalc = {
        name,
        displayName,
        type: field_1.TableCalculationType.NUMBER,
    };
    switch (type) {
        case 'percent_change_from_previous':
            return {
                ...baseCalc,
                template: {
                    type: field_1.TableCalculationTemplateType.PERCENT_CHANGE_FROM_PREVIOUS,
                    fieldId: tableCalc.fieldId,
                    orderBy: tableCalc.orderBy ?? [],
                    partitionBy: tableCalc.partitionBy ?? [],
                },
                format: {
                    type: field_1.CustomFormatType.PERCENT,
                    separator: field_1.NumberSeparator.DEFAULT,
                },
            };
        case 'percent_of_previous_value':
            return {
                ...baseCalc,
                template: {
                    type: field_1.TableCalculationTemplateType.PERCENT_OF_PREVIOUS_VALUE,
                    fieldId: tableCalc.fieldId,
                    orderBy: tableCalc.orderBy ?? [],
                    partitionBy: tableCalc.partitionBy ?? [],
                },
                format: {
                    type: field_1.CustomFormatType.PERCENT,
                    separator: field_1.NumberSeparator.DEFAULT,
                },
            };
        case 'percent_of_column_total':
            return {
                ...baseCalc,
                template: {
                    type: field_1.TableCalculationTemplateType.PERCENT_OF_COLUMN_TOTAL,
                    fieldId: tableCalc.fieldId,
                    partitionBy: tableCalc.partitionBy ?? [],
                },
                format: {
                    type: field_1.CustomFormatType.PERCENT,
                    separator: field_1.NumberSeparator.DEFAULT,
                },
            };
        case 'rank_in_column':
            return {
                ...baseCalc,
                template: {
                    type: field_1.TableCalculationTemplateType.RANK_IN_COLUMN,
                    fieldId: tableCalc.fieldId,
                },
                format: {
                    type: field_1.CustomFormatType.NUMBER,
                    separator: field_1.NumberSeparator.DEFAULT,
                },
            };
        case 'running_total':
            return {
                ...baseCalc,
                template: {
                    type: field_1.TableCalculationTemplateType.RUNNING_TOTAL,
                    fieldId: tableCalc.fieldId,
                },
                format: {
                    type: field_1.CustomFormatType.NUMBER,
                    separator: field_1.NumberSeparator.DEFAULT,
                },
            };
        case 'window_function': {
            const format = tableCalc.windowFunction === 'percent_rank' ||
                tableCalc.windowFunction === 'cume_dist'
                ? {
                    type: field_1.CustomFormatType.PERCENT,
                    separator: field_1.NumberSeparator.DEFAULT,
                }
                : {
                    type: field_1.CustomFormatType.NUMBER,
                    separator: field_1.NumberSeparator.DEFAULT,
                };
            // Convert frame clause string literals to enum types
            const frame = tableCalc.frame
                ? {
                    frameType: tableCalc.frame.frameType === 'rows'
                        ? field_1.FrameType.ROWS
                        : field_1.FrameType.RANGE,
                    start: tableCalc.frame.start
                        ? {
                            type: frameBoundaryStringToEnum(tableCalc.frame.start.type),
                            offset: tableCalc.frame.start.offset ?? undefined,
                        }
                        : undefined,
                    end: {
                        type: frameBoundaryStringToEnum(tableCalc.frame.end.type),
                        offset: tableCalc.frame.end.offset ?? undefined,
                    },
                }
                : undefined;
            return {
                ...baseCalc,
                template: {
                    type: field_1.TableCalculationTemplateType.WINDOW_FUNCTION,
                    windowFunction: tableCalc.windowFunction,
                    fieldId: tableCalc.fieldId,
                    orderBy: tableCalc.orderBy ?? [],
                    partitionBy: tableCalc.partitionBy ?? [],
                    frame,
                },
                format,
            };
        }
        default:
            return (0, assertUnreachable_1.default)(type, 'Unknown table calc type');
    }
}
function convertAiTableCalcsSchemaToTableCalcs(tableCalcs) {
    return tableCalcs?.map((tc) => convertTableCalcSchemaToTableCalc(tc)) ?? [];
}
//# sourceMappingURL=tableCalcs.js.map