import { Injectable } from "@nestjs/common";
import type { Prisma } from "@prisma/client";
import {
  TransactionService,
  type TransactionOptions,
  type TransactionResult,
} from "./services/transaction.service.js";

/**
 * Unit of Work — coordinates multi-entity operations within a single transaction.
 *
 * Wraps the existing TransactionService to provide a cleaner API for orchestrating
 * multiple repository operations atomically.
 *
 * @example
 * ```typescript
 * const result = await this.unitOfWork.execute(async (tx) => {
 *   const user = await tx.user.create({ data: userData });
 *   await tx.idMapping.create({ data: { userId: user.id, ... } });
 *   return user;
 * });
 * ```
 */
@Injectable()
export class UnitOfWork {
  constructor(private readonly transactionService: TransactionService) {}

  /**
   * Execute a function within a database transaction.
   * All Prisma operations on the `tx` client are atomic.
   */
  async execute<T>(
    fn: (tx: Prisma.TransactionClient) => Promise<T>,
    options?: TransactionOptions
  ): Promise<TransactionResult<T>> {
    return this.transactionService.executeTransaction(async (tx, context) => {
      context.addOperation("UnitOfWork.execute");
      return fn(tx);
    }, options);
  }
}
