import { Injectable } from '@nestjs/common';
import { PrismaService } from '../prisma/prisma.service';
import { Prisma } from '@prisma/client';

/**
 * 事务客户端类型
 * 使用 Prisma 官方的 TransactionClient 类型
 */
export type TransactionClient = Prisma.TransactionClient;

/**
 * 工作单元模式
 * 用于管理事务边界，确保多个仓库操作在同一事务中执行
 */
@Injectable()
export class UnitOfWork {
  private transactionClient: TransactionClient | null = null;

  constructor(private readonly prisma: PrismaService) {}

  /**
   * 获取当前事务客户端，如果没有活跃事务则返回普通客户端
   * 注意：返回 PrismaService 时可以兼容 TransactionClient 的操作
   */
  getClient(): TransactionClient | PrismaService {
    return this.transactionClient || this.prisma;
  }

  /**
   * 在事务中执行操作
   * 使用较长的超时时间以支持挖矿分配等大批量操作
   */
  async executeInTransaction<T>(
    operation: (client: TransactionClient) => Promise<T>,
    options?: {
      maxWait?: number;
      timeout?: number;
      isolationLevel?: Prisma.TransactionIsolationLevel;
    },
  ): Promise<T> {
    return this.prisma.$transaction(
      async (tx) => {
        this.transactionClient = tx as TransactionClient;
        try {
          return await operation(tx as TransactionClient);
        } finally {
          this.transactionClient = null;
        }
      },
      {
        maxWait: options?.maxWait ?? 10000, // 默认10秒等待获取事务
        timeout: options?.timeout ?? 60000, // 默认60秒事务超时（挖矿分配可能需要较长时间）
        isolationLevel: options?.isolationLevel ?? Prisma.TransactionIsolationLevel.ReadCommitted,
      },
    );
  }

  /**
   * 是否在事务中
   */
  isInTransaction(): boolean {
    return this.transactionClient !== null;
  }
}
