/**
 * Cross-realm brand for ServiceError instances.
 *
 * `Symbol.for()` returns the *same* symbol across every copy of this module,
 * so even if a bundler/packer (e.g. docker-prep tarballs) produces a second
 * physical copy of `@bytelyst/errors`, branded instances stay recognizable.
 */
const SERVICE_ERROR_BRAND = Symbol.for('@bytelyst/errors.ServiceError');

/**
 * Base error class for typed HTTP service errors.
 * All specific error types extend this class.
 */
export class ServiceError extends Error {
  constructor(
    public statusCode: number,
    message: string,
    public details?: Record<string, unknown>
  ) {
    super(message);
    this.name = 'ServiceError';
    // Brand the instance so `instanceof ServiceError` works even when this
    // module has been duplicated and prototype identity no longer matches.
    Object.defineProperty(this, SERVICE_ERROR_BRAND, {
      value: true,
      enumerable: false,
      writable: false,
      configurable: false,
    });
  }

  /**
   * Custom `instanceof` that is resilient to duplicated module copies.
   *
   * - For the base `ServiceError`, recognize any brand-carrying instance
   *   regardless of which physical copy of this module created it.
   * - For subclasses, fall back to the standard prototype-chain check so that
   *   semantics like `notFound instanceof BadRequestError === false` hold.
   */
  static [Symbol.hasInstance](instance: unknown): boolean {
    if (typeof instance !== 'object' || instance === null) return false;
    if (this === ServiceError) {
      return (instance as Record<symbol, unknown>)[SERVICE_ERROR_BRAND] === true;
    }
    const proto = (this as unknown as { prototype: object }).prototype;
    return Object.prototype.isPrototypeOf.call(proto, instance);
  }
}
