import { Injectable } from '@nestjs/common';
import { EventEmitter2 } from '@nestjs/event-emitter';
import { EntityContext } from './entity-context.interface';

@Injectable()
export class EntityEventsService {
  constructor(private readonly eventEmitter: EventEmitter2) {}

  async emitBeforeAdd<T>(
    entityType: string,
    fields: Partial<T>,
    context?: EntityContext,
  ): Promise<void> {
    if (context?.skipEvents) return;
    await this.eventEmitter.emitAsync(`crm.${entityType}.beforeAdd`, {
      fields,
      context,
    });
  }

  async emitAfterAdd<T>(entityType: string, entity: T, context?: EntityContext): Promise<void> {
    if (context?.skipEvents) return;
    await this.eventEmitter.emitAsync(`crm.${entityType}.afterAdd`, {
      entity,
      context,
    });
  }

  async emitBeforeUpdate<T>(
    entityType: string,
    id: string,
    fields: Partial<T>,
    context?: EntityContext,
  ): Promise<void> {
    if (context?.skipEvents) return;
    await this.eventEmitter.emitAsync(`crm.${entityType}.beforeUpdate`, {
      id,
      fields,
      context,
    });
  }

  async emitAfterUpdate<T>(
    entityType: string,
    entity: T,
    oldEntity: T,
    context?: EntityContext,
  ): Promise<void> {
    if (context?.skipEvents) return;
    await this.eventEmitter.emitAsync(`crm.${entityType}.afterUpdate`, {
      entity,
      oldEntity,
      context,
    });
  }

  async emitBeforeDelete(entityType: string, id: string, context?: EntityContext): Promise<void> {
    if (context?.skipEvents) return;
    await this.eventEmitter.emitAsync(`crm.${entityType}.beforeDelete`, {
      id,
      context,
    });
  }

  async emitAfterDelete(entityType: string, id: string, context?: EntityContext): Promise<void> {
    if (context?.skipEvents) return;
    await this.eventEmitter.emitAsync(`crm.${entityType}.afterDelete`, {
      id,
      context,
    });
  }

  /** Emit a custom domain event (e.g. crm.deal.won) */
  async emit(event: string, payload: Record<string, any>): Promise<void> {
    await this.eventEmitter.emitAsync(event, payload);
  }
}
