import { PopulatePath } from '../enums.js';
const populatePathMembers = Object.values(PopulatePath);
/** Base class for naming strategies, providing default implementations for common naming conventions. */
export class AbstractNamingStrategy {
  getClassName(file, separator = '-') {
    const name = file.split('.')[0];
    const ret = name.replace(new RegExp(`(?:${separator})+(\\w)`, 'ug'), (_, p1) => p1.toUpperCase());
    return ret.charAt(0).toUpperCase() + ret.slice(1);
  }
  classToMigrationName(timestamp, customMigrationName) {
    let migrationName = `Migration${timestamp}`;
    if (customMigrationName) {
      migrationName += `_${customMigrationName}`;
    }
    return migrationName;
  }
  indexName(tableName, columns, type) {
    /* v8 ignore next */
    if (tableName.includes('.')) {
      tableName = tableName.substring(tableName.indexOf('.') + 1);
    }
    if (type === 'primary') {
      return `${tableName}_pkey`;
    }
    columns = columns.map(col => col.replace(/\./g, '_'));
    if (type === 'sequence') {
      return `${tableName}_${columns.join('_')}_seq`;
    }
    if (columns.length > 0) {
      return `${tableName}_${columns.join('_')}_${type}`;
    }
    return `${tableName}_${type}`;
  }
  /**
   * @inheritDoc
   */
  getEntityName(tableName, schemaName) {
    const name = /^[^$_\p{ID_Start}]/u.exec(tableName) ? `E_${tableName}` : tableName;
    return this.getClassName(
      name.replaceAll(/[^\u200C\u200D\p{ID_Continue}]+/gu, r =>
        r
          .split('')
          .map(c => `$${c.codePointAt(0)}`)
          .join(''),
      ),
      '_',
    );
  }
  columnNameToProperty(columnName) {
    const propName = columnName.replace(/[_\- ]+(\w)/gu, (_, p1) => p1.toUpperCase());
    if (populatePathMembers.includes(propName.replace(/^\${2,}/u, '$$').replace(/^\$\*$/u, '*'))) {
      return `$${propName}`;
    }
    return propName;
  }
  /**
   * @inheritDoc
   */
  getEnumClassName(columnName, tableName, schemaName) {
    return this.getEntityName(tableName ? `${tableName}_${columnName}` : columnName, schemaName);
  }
  /**
   * @inheritDoc
   */
  getEnumTypeName(columnName, tableName, schemaName) {
    return 'T' + this.getEnumClassName(columnName, tableName, schemaName);
  }
  /**
   * @inheritDoc
   */
  enumValueToEnumProperty(enumValue, columnName, tableName, schemaName) {
    return enumValue.toUpperCase();
  }
  aliasName(entityName, index) {
    // Take only the first letter of the prefix to keep character counts down since some engines have character limits
    return entityName.charAt(0).toLowerCase() + index;
  }
  /**
   * @inheritDoc
   */
  inverseSideName(entityName, propertyName, kind) {
    if (kind === 'm:n') {
      return propertyName + 'Inverse';
    }
    const suffix = kind === '1:m' && !entityName.endsWith('Collection') ? 'Collection' : '';
    if (entityName.length === 1) {
      return entityName[0].toLowerCase() + suffix;
    }
    return entityName[0].toLowerCase() + entityName.substring(1) + suffix;
  }
  /**
   * @inheritDoc
   */
  manyToManyPropertyName(ownerEntityName, targetEntityName, pivotTableName, ownerTableName, schemaName) {
    return this.columnNameToProperty(pivotTableName.replace(new RegExp('^' + ownerTableName + '_'), ''));
  }
  /**
   * @inheritDoc
   */
  discriminatorColumnName(baseName) {
    return this.propertyToColumnName(baseName + 'Type');
  }
}
