"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createTemporaryVirtualView = exports.createVirtualView = void 0;
const exploreCompiler_1 = require("../compiler/exploreCompiler");
const dbt_1 = require("../types/dbt");
const explore_1 = require("../types/explore");
const field_1 = require("../types/field");
const projects_1 = require("../types/projects");
const timeFrames_1 = require("./timeFrames");
const warehouse_1 = require("./warehouse");
const createVirtualView = (virtualViewName, sql, columns, warehouseClient, label, parameterValues) => {
    const exploreCompiler = new exploreCompiler_1.ExploreCompiler(warehouseClient);
    const fieldQuoteChar = warehouseClient.getFieldQuoteChar();
    const dimensions = columns.reduce((acc, column) => {
        acc[column.reference] = {
            name: column.reference,
            label: (0, field_1.friendlyName)(column.reference),
            type: column.type ?? field_1.DimensionType.STRING,
            table: virtualViewName,
            fieldType: field_1.FieldType.DIMENSION,
            sql: `${fieldQuoteChar}${column.reference}${fieldQuoteChar}`,
            tableLabel: (0, field_1.friendlyName)(virtualViewName),
            hidden: false,
        };
        return acc;
    }, {});
    const compiledTable = {
        name: virtualViewName,
        label: label || (0, field_1.friendlyName)(virtualViewName),
        sqlTable: `(${sql})`, // Wrap the sql in a subquery to avoid issues with reserved words
        dimensions,
        metrics: {},
        lineageGraph: { nodes: [], edges: [] },
        database: warehouseClient.credentials.type,
        schema: '', // TODO: what should this be?
    };
    const explore = exploreCompiler.compileExplore({
        name: virtualViewName,
        label: label || (0, field_1.friendlyName)(virtualViewName),
        tags: [],
        baseTable: virtualViewName,
        joinedTables: [],
        tables: { [virtualViewName]: compiledTable },
        targetDatabase: warehouseClient.getAdapterType(),
        meta: {},
    });
    const hasSavedParameters = parameterValues && Object.keys(parameterValues).length > 0;
    const virtualView = {
        ...explore,
        type: explore_1.ExploreType.VIRTUAL,
        ...(hasSavedParameters
            ? { savedParameterValues: parameterValues }
            : {}),
    };
    return virtualView;
};
exports.createVirtualView = createVirtualView;
const createTemporaryVirtualView = (virtualViewName, sql, columns) => {
    // Create a fake warehouseClient for compilation purposes
    const fakeWarehouseClient = {
        credentials: {
            type: projects_1.WarehouseTypes.BIGQUERY,
            project: '',
            dataset: '',
            timeoutSeconds: 0,
            priority: 'interactive',
            keyfileContents: {},
            retries: 3,
            location: '',
            maximumBytesBilled: 0,
        },
        getCatalog: async () => ({}),
        streamQuery: async () => { },
        executeAsyncQuery: async () => ({
            queryId: null,
            queryMetadata: null,
            totalRows: 0,
            durationMs: 0,
            phaseTimings: {},
        }),
        runQuery: async () => ({ fields: {}, rows: [] }),
        test: async () => { },
        getStartOfWeek: () => timeFrames_1.WeekDay.MONDAY,
        getAdapterType: () => dbt_1.SupportedDbtAdapter.BIGQUERY,
        supportsCteMaterialization: () => true,
        getStringQuoteChar: () => "'",
        getEscapeStringQuoteChar: () => "''",
        getFieldQuoteChar: () => '"',
        getFloatingType: () => 'FLOAT',
        getNullSafeEqualSql: warehouse_1.defaultNullSafeEqualSql,
        getNullSafeEqualJoinSql: warehouse_1.defaultNullSafeEqualSql,
        getMetricSql: () => '',
        concatString: (...args) => args.join(''),
        getAllTables: async () => [],
        getFields: async () => ({}),
        parseWarehouseCatalog: () => ({}),
        parseError: (error) => error,
        escapeString: (value) => value,
        castToTimestamp: (date) => `CAST('${date.toISOString()}' AS TIMESTAMP)`,
        getIntervalSql: (value, unit) => `INTERVAL '${value} ${unit}'`,
        getTimestampDiffSeconds: (startTimestampSql, endTimestampSql) => `EXTRACT(EPOCH FROM (${endTimestampSql} - ${startTimestampSql}))`,
        getMedianSql: (valueSql) => `PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY ${valueSql})`,
        buildArray: (elements) => `ARRAY[${elements.join(', ')}]`,
        buildArrayAgg: (expression, orderBy) => orderBy
            ? `ARRAY_AGG(${expression} ORDER BY ${orderBy})`
            : `ARRAY_AGG(${expression})`,
    };
    return (0, exports.createVirtualView)(virtualViewName, sql, columns, fakeWarehouseClient);
};
exports.createTemporaryVirtualView = createTemporaryVirtualView;
//# sourceMappingURL=virtualView.js.map