"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var tables_publisher_exports = {};
__export(tables_publisher_exports, {
  TablesPublisher: () => TablesPublisher
});
module.exports = __toCommonJS(tables_publisher_exports);
var sdk = __toESM(require("@botpress/sdk"));
var errors = __toESM(require("../errors"));
var schemas = __toESM(require("./schemas"));
class TablesPublisher {
  _api;
  _logger;
  _prompt;
  constructor({
    api,
    logger: logger2,
    prompt
  }) {
    this._api = api;
    this._logger = logger2;
    this._prompt = prompt;
  }
  async deployTables({ botId, botDefinition }) {
    const api = this._api.switchBot(botId);
    this._logger.log("Synchronizing tables...");
    const tablesFromBotDef = Object.entries(botDefinition.tables ?? {});
    const listTableResult = await api.safeListTables({});
    if (!listTableResult.success) {
      this._logger.warn("Tables API is not available, skipping table deployment.");
      return;
    }
    const { tables: existingTables } = listTableResult;
    for (const [tableName, tableDef] of tablesFromBotDef) {
      const existingTable = existingTables.find((t) => t.name === tableName);
      this._logger.log(`Deploying table "${tableName}"...`);
      if (existingTable) {
        await this._deployExistingTable({ api, existingTable, updatedTableDef: tableDef });
      } else {
        await this._deployNewTable({ api, tableName, tableDef });
      }
    }
    for (const existingTable of existingTables) {
      if (!tablesFromBotDef.find(([tableName]) => tableName === existingTable.name)) {
        this._logger.log(
          `Table "${existingTable.name}" was previously defined but is not present in your bot definition. This table will be ignored. If you wish to delete this table, you may do so from the studio.`
        );
      }
    }
  }
  async _deployExistingTable({
    api,
    existingTable,
    updatedTableDef
  }) {
    if (existingTable.frozen) {
      this._logger.warn(`Table "${existingTable.name}" is frozen and will not be updated.`);
      return;
    }
    const existingColumns = existingTable.schema.properties;
    const updatedColumns = await this._parseTableColumns({ tableName: existingTable.name, tableDef: updatedTableDef });
    for (const [columnName, existingColumn] of Object.entries(existingColumns)) {
      const updatedColumn = updatedColumns[columnName];
      if (!updatedColumn) {
        const wishToContinue = await this._warnAndConfirm(
          `Column "${columnName}" is missing from the schema of table "${existingTable.name}" in your bot definition. If you are attempting to rename this column, please do so from the studio. Renaming a column in your bot definition will cause a new column to be created. If this is not a rename and you wish to proceed, the old column will be kept unchanged. You can delete columns from the studio if you no longer need them.`
        );
        if (!wishToContinue) {
          return;
        }
      }
      if (updatedColumn && existingColumn.type !== updatedColumn.type) {
        const wishToContinue = await this._warnAndConfirm(
          `DATA LOSS WARNING: Type of column "${columnName}" has changed from "${existingColumn.type}" to "${updatedColumn.type}" in table "${existingTable.name}". If you proceed, the value of this column will be reset to NULL for all rows in the table.`
        );
        if (!wishToContinue) {
          return;
        }
      }
    }
    await api.client.updateTable({
      table: existingTable.name,
      schema: sdk.transforms.toJSONSchemaLegacy(updatedTableDef.schema),
      frozen: updatedTableDef.frozen,
      tags: updatedTableDef.tags,
      isComputeEnabled: updatedTableDef.isComputeEnabled
    });
    this._logger.success(`Table "${existingTable.name}" has been updated`);
  }
  async _parseTableColumns({
    tableName,
    tableDef
  }) {
    const columns = sdk.transforms.toJSONSchemaLegacy(tableDef.schema).properties;
    const validColumns = await Promise.all(
      Object.entries(columns).map(async ([columnName, columnSchema]) => {
        const validatedSchema = await schemas.columnSchema.safeParseAsync(columnSchema);
        if (!validatedSchema.success) {
          throw new errors.BotpressCLIError(
            `Column "${columnName}" in table "${tableName}" has an invalid schema: ${validatedSchema.error.message}`
          );
        }
        return [columnName, validatedSchema.data];
      })
    );
    return Object.fromEntries(validColumns);
  }
  async _warnAndConfirm(warningMessage, confirmMessage = "Are you sure you want to continue?") {
    this._logger.warn(warningMessage);
    const confirm = await this._prompt.confirm(confirmMessage);
    if (!confirm) {
      this._logger.log("Aborted");
      return false;
    }
    return true;
  }
  async _deployNewTable({
    api,
    tableName,
    tableDef
  }) {
    await api.client.createTable({
      name: tableName,
      schema: sdk.transforms.toJSONSchemaLegacy(tableDef.schema),
      frozen: tableDef.frozen,
      tags: tableDef.tags,
      factor: tableDef.factor,
      isComputeEnabled: tableDef.isComputeEnabled
    });
    this._logger.success(`Table "${tableName}" has been created`);
  }
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  TablesPublisher
});
//# sourceMappingURL=tables-publisher.js.map
