import { Injectable, Logger } from '@nestjs/common';
import { PrismaService } from '../prisma/prisma.service';
import { IUnitOfWork, PrismaTransactionClient } from './unit-of-work.interface';

/**
 * Unit of Work 实现
 * 使用 Prisma Interactive Transaction 确保多个仓库操作的原子性
 */
@Injectable()
export class UnitOfWorkService implements IUnitOfWork {
  private readonly logger = new Logger(UnitOfWorkService.name);

  constructor(private readonly prisma: PrismaService) {}

  /**
   * 在事务中执行工作
   * 事务中的所有操作要么全部成功，要么全部回滚
   */
  async runInTransaction<T>(
    work: (tx: PrismaTransactionClient) => Promise<T>,
  ): Promise<T> {
    this.logger.debug('[UoW] Starting transaction');

    try {
      const result = await this.prisma.$transaction(
        async (tx) => {
          return await work(tx);
        },
        {
          // 设置较长的超时时间，因为某些操作可能需要更多时间
          timeout: 30000, // 30 秒
          // 使用 ReadCommitted 隔离级别，平衡一致性和性能
          isolationLevel: 'ReadCommitted',
        },
      );

      this.logger.debug('[UoW] Transaction committed successfully');
      return result;
    } catch (error) {
      this.logger.error('[UoW] Transaction rolled back due to error', error);
      throw error;
    }
  }
}
