import { Transaction } from '../../../domain/entities/transaction';
import { NotFoundError } from '../../../domain/errors/not-found-error';
import { ValidationError } from '../../../domain/errors/validation-error';
import { ITransactionRepository } from '../../../domain/repositories/transaction-repository';
import { UpdateTransactionInput } from '../../dto/transaction.dto';
import { IDomainEventPublisher } from '../../ports/domain-event-publisher';
import { TransactionUpdatedEvent } from '../../../domain/events/transaction-updated.event';

export class UpdateTransactionUseCase {
  constructor(
    private readonly transactionRepository: ITransactionRepository,
    private readonly eventPublisher: IDomainEventPublisher,
  ) {}

  async execute(id: string, input: UpdateTransactionInput): Promise<Transaction> {
    const transaction = await this.transactionRepository.findById(id);
    if (!transaction) {
      throw new NotFoundError('Transaction', id);
    }

    if (input.status === undefined && input.block === undefined) {
      throw new ValidationError('At least one field must be provided for update', {
        status: ['Missing'],
        block: ['Missing'],
      });
    }

    const updatedStatus = input.status ?? transaction.status;
    const updatedBlock = input.block !== undefined ? input.block : transaction.block;

    const updated = transaction.updateStatus(updatedStatus, updatedBlock ?? undefined);
    const saved = await this.transactionRepository.update(updated);
    this.eventPublisher.publish(new TransactionUpdatedEvent(saved));
    return saved;
  }
}
