import AnalyticsTableEngine from "../../../Types/AnalyticsDatabase/AnalyticsTableEngine";
import AnalyticsTableColumn from "../../../Types/AnalyticsDatabase/TableColumn";
import TableColumnType from "../../../Types/AnalyticsDatabase/TableColumnType";
import ModelPermission from "../../../Types/BaseDatabase/ModelPermission";
import BadDataException from "../../../Types/Exception/BadDataException";
import Text from "../../../Types/Text";
import CommonModel from "./CommonModel";
export default class AnalyticsBaseModel extends CommonModel {
    constructor(data) {
        super({
            tableColumns: data.tableColumns,
        });
        this._tableEngine = AnalyticsTableEngine.MergeTree;
        this._primaryKeys = [];
        this._partitionKey = "";
        this._tableSettings = undefined;
        this._sortKeys = [];
        /*
         * Column that `AnalyticsDatabaseService._findBy` falls back to
         * when the caller didn't pass a `sort`. `createdAt` (the historical
         * default) is not part of the ClickHouse sort key on heavy
         * analytics tables (Log/Span/Metric/...), so a default list query
         * over those tables triggers a full sort. Per-model overrides
         * point at a column that participates in the sort key.
         */
        this._defaultSortColumn = "createdAt";
        this._singularName = "";
        this._pluralName = "";
        this._allowAccessIfSubscriptionIsUnpaid = false;
        this._tableName = "";
        this._enableDocumentation = false;
        this._tableDescription = "";
        this._isMasterAdminApiDocs = false;
        this._projections = [];
        this._materializedViews = [];
        this._enableMCP = false;
        this._ttlExpression = "";
        this.tableName = data.tableName;
        const columns = [...data.tableColumns];
        if (data.tableEngine) {
            this.tableEngine = data.tableEngine;
        }
        columns.push(new AnalyticsTableColumn({
            key: "_id",
            title: "ID",
            description: "ID of this object",
            required: true,
            type: TableColumnType.ObjectID,
            /*
             * Ids are UUIDv7 (time-ordered — see ObjectID.generateTimeOrdered),
             * so consecutive rows share their 48-bit timestamp prefix and ZSTD
             * compresses them well; random v4 ids were incompressible.
             */
            codec: { codec: "ZSTD", level: 1 },
        }));
        columns.push(new AnalyticsTableColumn({
            key: "createdAt",
            title: "Created",
            description: "Date and Time when the object was created.",
            required: true,
            type: TableColumnType.Date,
        }));
        if (!data.primaryKeys || data.primaryKeys.length === 0) {
            throw new BadDataException("Primary keys are required");
        }
        // check if primary keys are subset of tableColumns
        data.primaryKeys.forEach((primaryKey) => {
            const column = columns.find((column) => {
                return column.key === primaryKey;
            });
            if (!column) {
                throw new BadDataException("Primary key " + primaryKey + " is not part of tableColumns");
            }
            if (!column.required) {
                throw new BadDataException("Primary key " +
                    primaryKey +
                    " is not required. Primary keys must be required.");
            }
        });
        // check if sort keys are subset of tableColumns
        data.sortKeys.forEach((sortKey) => {
            const column = columns.find((column) => {
                return column.key === sortKey;
            });
            if (!column) {
                throw new BadDataException("Sort key " + sortKey + " is not part of tableColumns");
            }
        });
        this.primaryKeys = data.primaryKeys;
        this.sortKeys = data.sortKeys;
        this.tableColumns = columns;
        this.singularName = data.singularName;
        this.pluralName = data.pluralName;
        this.tableBillingAccessControl = data.tableBillingAccessControl;
        this.allowAccessIfSubscriptionIsUnpaid =
            data.allowAccessIfSubscriptionIsUnpaid || false;
        this.accessControl = data.accessControl;
        this.enableWorkflowOn = data.enableWorkflowOn;
        this.crudApiPath = data.crudApiPath;
        this.enableDocumentation = data.enableDocumentation || false;
        this.tableDescription = data.tableDescription || "";
        this.isMasterAdminApiDocs = data.isMasterAdminApiDocs || false;
        this.enableRealtimeEventsOn = data.enableRealtimeEventsOn;
        this.partitionKey = data.partitionKey;
        this.tableSettings = data.tableSettings;
        this.projections = data.projections || [];
        this.materializedViews = data.materializedViews || [];
        this.enableMCP = data.enableMCP || false;
        this.ttlExpression = data.ttlExpression || "";
        /*
         * Validate the override matches the schema. We deliberately do
         * NOT require the column to be in `sortKeys` — it must just
         * exist on the table; the caller picks a column they know is
         * indexed (typically the timestamp column at position 2 of the
         * sort key, after `projectId`).
         */
        if (data.defaultSortColumn) {
            const column = columns.find((column) => {
                return column.key === data.defaultSortColumn;
            });
            if (!column) {
                throw new BadDataException("defaultSortColumn " +
                    data.defaultSortColumn +
                    " is not part of tableColumns");
            }
            this.defaultSortColumn = data.defaultSortColumn;
        }
    }
    get enableWorkflowOn() {
        return this._enableWorkflowOn;
    }
    set enableWorkflowOn(v) {
        this._enableWorkflowOn = v;
    }
    get accessControl() {
        return this._accessControl;
    }
    set accessControl(v) {
        this._accessControl = v;
    }
    get tableEngine() {
        return this._tableEngine;
    }
    set tableEngine(v) {
        this._tableEngine = v;
    }
    get enableRealtimeEventsOn() {
        return this._enableRealtimeEventsOn;
    }
    set enableRealtimeEventsOn(v) {
        this._enableRealtimeEventsOn = v;
    }
    get primaryKeys() {
        return this._primaryKeys;
    }
    set primaryKeys(v) {
        this._primaryKeys = v;
    }
    get partitionKey() {
        return this._partitionKey;
    }
    set partitionKey(v) {
        this._partitionKey = v;
    }
    get tableSettings() {
        return this._tableSettings;
    }
    set tableSettings(v) {
        this._tableSettings = v;
    }
    get sortKeys() {
        return this._sortKeys;
    }
    set sortKeys(v) {
        this._sortKeys = v;
    }
    get defaultSortColumn() {
        return this._defaultSortColumn;
    }
    set defaultSortColumn(v) {
        this._defaultSortColumn = v;
    }
    get singularName() {
        return this._singularName;
    }
    set singularName(v) {
        this._singularName = v;
    }
    get pluralName() {
        return this._pluralName;
    }
    set pluralName(v) {
        this._pluralName = v;
    }
    get tableBillingAccessControl() {
        return this._tableBillingAccessControl;
    }
    set tableBillingAccessControl(v) {
        this._tableBillingAccessControl = v;
    }
    get allowAccessIfSubscriptionIsUnpaid() {
        return this._allowAccessIfSubscriptionIsUnpaid;
    }
    set allowAccessIfSubscriptionIsUnpaid(v) {
        this._allowAccessIfSubscriptionIsUnpaid = v;
    }
    get tableName() {
        return this._tableName;
    }
    set tableName(v) {
        this._tableName = v;
    }
    get crudApiPath() {
        return this._crudApiPath;
    }
    set crudApiPath(v) {
        this._crudApiPath = v;
    }
    get enableDocumentation() {
        return this._enableDocumentation;
    }
    set enableDocumentation(v) {
        this._enableDocumentation = v;
    }
    get tableDescription() {
        return this._tableDescription;
    }
    set tableDescription(v) {
        this._tableDescription = v;
    }
    get isMasterAdminApiDocs() {
        return this._isMasterAdminApiDocs;
    }
    set isMasterAdminApiDocs(v) {
        this._isMasterAdminApiDocs = v;
    }
    get projections() {
        return this._projections;
    }
    set projections(v) {
        this._projections = v;
    }
    get materializedViews() {
        return this._materializedViews;
    }
    set materializedViews(v) {
        this._materializedViews = v;
    }
    get enableMCP() {
        return this._enableMCP;
    }
    set enableMCP(v) {
        this._enableMCP = v;
    }
    get ttlExpression() {
        return this._ttlExpression;
    }
    set ttlExpression(v) {
        this._ttlExpression = v;
    }
    getTenantColumn() {
        const column = this.tableColumns.find((column) => {
            return column.isTenantId;
        });
        if (!column) {
            return null;
        }
        return column;
    }
    getTenantColumnValue() {
        const column = this.getTenantColumn();
        if (!column) {
            return null;
        }
        return this.getColumnValue(column.key);
    }
    getRequiredColumns() {
        return this.tableColumns.filter((column) => {
            return column.required;
        });
    }
    isDefaultValueColumn(columnName) {
        const column = this.getTableColumn(columnName);
        if (!column) {
            return false;
        }
        return column.isDefaultValueColumn;
    }
    getDefaultValueForColumn(columnName) {
        const column = this.getTableColumn(columnName);
        if (!column) {
            throw new BadDataException("Column " + columnName + " not found");
        }
        return column.defaultValue;
    }
    getColumnBillingAccessControl(columnName) {
        const column = this.getTableColumn(columnName);
        if (!column) {
            return null;
        }
        return column.billingAccessControl || null;
    }
    get id() {
        return this.getColumnValue("_id");
    }
    set id(v) {
        this.setColumnValue("_id", v);
    }
    get _id() {
        return this.getColumnValue("_id");
    }
    set _id(v) {
        this.setColumnValue("_id", v);
    }
    get createdAt() {
        return this.getColumnValue("createdAt");
    }
    set createdAt(v) {
        this.setColumnValue("createdAt", v);
    }
    getAPIDocumentationPath() {
        /*
         * Prefer the public CRUD API slug (e.g. "/logs" -> "logs") so the
         * docs URL and the in-app "API Docs" link mirror the real endpoint,
         * rather than the internal ClickHouse table name (e.g. "LogItemV2").
         */
        if (this.crudApiPath) {
            return this.crudApiPath.toString().replace(/^\/+/, "");
        }
        return Text.pascalCaseToDashes(this.tableName);
    }
    getColumnAccessControlFor(columnName) {
        const tableColumn = this.tableColumns.find((column) => {
            return column.key === columnName;
        });
        if (!tableColumn || !tableColumn.accessControl) {
            return null;
        }
        return tableColumn.accessControl;
    }
    getColumnAccessControlForAllColumns() {
        const dictionary = {};
        for (const column of this.tableColumns) {
            if (column.accessControl) {
                dictionary[column.key] = column.accessControl;
            }
        }
        return dictionary;
    }
    getReadPermissions() {
        var _a;
        return ((_a = this.accessControl) === null || _a === void 0 ? void 0 : _a.read) || [];
    }
    getCreatePermissions() {
        var _a;
        return ((_a = this.accessControl) === null || _a === void 0 ? void 0 : _a.create) || [];
    }
    getUpdatePermissions() {
        var _a;
        return ((_a = this.accessControl) === null || _a === void 0 ? void 0 : _a.update) || [];
    }
    getDeletePermissions() {
        var _a;
        return ((_a = this.accessControl) === null || _a === void 0 ? void 0 : _a.delete) || [];
    }
    getReadBillingPlan() {
        var _a;
        return ((_a = this.tableBillingAccessControl) === null || _a === void 0 ? void 0 : _a.read) || null;
    }
    getCreateBillingPlan() {
        var _a;
        return ((_a = this.tableBillingAccessControl) === null || _a === void 0 ? void 0 : _a.create) || null;
    }
    getUpdateBillingPlan() {
        var _a;
        return ((_a = this.tableBillingAccessControl) === null || _a === void 0 ? void 0 : _a.update) || null;
    }
    getDeleteBillingPlan() {
        var _a;
        return ((_a = this.tableBillingAccessControl) === null || _a === void 0 ? void 0 : _a.delete) || null;
    }
    isEntityColumn(_columnName) {
        // Analytics model does not suppprt entity columns.
        return false;
    }
    hasColumn(columnName) {
        return this.tableColumns.some((column) => {
            return column.key === columnName;
        });
    }
    isFileColumn(_columnName) {
        // Analytics model does not suppprt file columns.
        return false;
    }
    hasCreatePermissions(userProjectPermissions, columnName) {
        var _a;
        let modelPermission = ((_a = this.accessControl) === null || _a === void 0 ? void 0 : _a.create) || [];
        if (columnName) {
            const columnAccessControl = this.getColumnAccessControlFor(columnName);
            if (columnAccessControl) {
                modelPermission = columnAccessControl.create;
            }
        }
        return ModelPermission.hasPermissions(userProjectPermissions, modelPermission);
    }
    hasReadPermissions(userProjectPermissions, columnName) {
        var _a;
        let modelPermission = ((_a = this.accessControl) === null || _a === void 0 ? void 0 : _a.read) || [];
        if (columnName) {
            const columnAccessControl = this.getColumnAccessControlFor(columnName);
            if (columnAccessControl) {
                modelPermission = columnAccessControl.read;
            }
        }
        return ModelPermission.hasPermissions(userProjectPermissions, modelPermission);
    }
    hasDeletePermissions(userProjectPermissions) {
        var _a;
        const modelPermission = ((_a = this.accessControl) === null || _a === void 0 ? void 0 : _a.delete) || [];
        return ModelPermission.hasPermissions(userProjectPermissions, modelPermission);
    }
    hasUpdatePermissions(userProjectPermissions, columnName) {
        var _a;
        let modelPermission = ((_a = this.accessControl) === null || _a === void 0 ? void 0 : _a.update) || [];
        if (columnName) {
            const columnAccessControl = this.getColumnAccessControlFor(columnName);
            if (columnAccessControl) {
                modelPermission = columnAccessControl.update;
            }
        }
        return ModelPermission.hasPermissions(userProjectPermissions, modelPermission);
    }
}
//# sourceMappingURL=AnalyticsBaseModel.js.map