import { BaseEntity } from './base-entity';
import { type DomainEvent } from './domain-event';

export abstract class AggregateRoot<TId = string> extends BaseEntity<TId> {
  private _domainEvents: DomainEvent[] = [];

  get domainEvents(): ReadonlyArray<DomainEvent> {
    return [...this._domainEvents];
  }

  /**
   * Returns all domain events that have not yet been published.
   * Use this to inspect pending events before committing.
   */
  getUncommittedEvents(): DomainEvent[] {
    return [...this._domainEvents];
  }

  protected addDomainEvent(event: DomainEvent): void {
    this._domainEvents.push(event);
  }

  /**
   * Clears and returns all uncommitted domain events.
   * Call this after persisting the aggregate and before publishing events.
   */
  clearDomainEvents(): DomainEvent[] {
    const events = [...this._domainEvents];
    this._domainEvents = [];
    return events;
  }

  /**
   * Alias for clearDomainEvents(). Marks all pending events as committed
   * by clearing the internal event list and returning them for publishing.
   */
  commit(): DomainEvent[] {
    return this.clearDomainEvents();
  }
}
