import { inspect } from '../logging/inspect.js';
/** @internal */
export const ORM_TYPE = Symbol.for('@mikro-orm/type');
/** Abstract base class for custom property types that handle conversion between JS and database representations. */
export class Type {
  static types = new Map();
  platform;
  meta;
  prop;
  /**
   * Converts a value from its JS representation to its database representation of this type.
   */
  convertToDatabaseValue(value, platform, context) {
    return value;
  }
  /**
   * Converts a value from its database representation to its JS representation of this type.
   */
  convertToJSValue(value, platform, context) {
    return value;
  }
  /**
   * How should the raw database values be compared? Used in `EntityComparator`.
   * Possible values: string | number | bigint | boolean | date | any | buffer | array
   */
  compareAsType() {
    return 'any';
  }
  get runtimeType() {
    const compareType = this.compareAsType();
    return compareType === 'any' ? 'string' : compareType;
  }
  get name() {
    return this.constructor.name;
  }
  /**
   * When a value is hydrated, we convert it back to the database value to ensure comparability,
   * as often the raw database response is not the same as the `convertToDatabaseValue` result.
   * This allows to disable the additional conversion in case you know it is not needed.
   */
  ensureComparable(meta, prop) {
    return true;
  }
  /**
   * Converts a value from its JS representation to its serialized JSON form of this type.
   * By default uses the runtime value.
   */
  toJSON(value, platform) {
    return value;
  }
  /**
   * Gets the SQL declaration snippet for a field of this type.
   */
  getColumnType(prop, platform) {
    return prop.columnTypes?.[0] ?? platform.getTextTypeDeclarationSQL(prop);
  }
  static getType(cls) {
    const key = cls.name;
    if (!Type.types.has(key)) {
      Type.types.set(key, new cls());
    }
    return Type.types.get(key);
  }
  /**
   * Checks whether the argument is instance of `Type`.
   */
  static isMappedType(data) {
    return !!data?.__mappedType;
  }
  /**
   * @internal
   * Returns the built-in type registry key if the given constructor is a branded ORM type
   * (not a user subclass). Uses `Symbol.for()` so it works across CJS/ESM module graphs.
   */
  static getOrmType(cls) {
    return Object.hasOwn(cls, ORM_TYPE) ? cls[ORM_TYPE] : undefined;
  }
  /** @ignore */
  [Symbol.for('nodejs.util.inspect.custom')](depth = 2) {
    const object = { ...this };
    const hidden = ['prop', 'platform', 'meta'];
    hidden.forEach(k => delete object[k]);
    const ret = inspect(object, { depth });
    const name = this.constructor.name;
    /* v8 ignore next */
    return ret === '[Object]' ? `[${name}]` : name + ' ' + ret;
  }
}
Object.defineProperties(Type.prototype, {
  __mappedType: { value: true, enumerable: false, writable: false },
});
