import { TransactionRequest as PrismaTransactionRequest } from '@prisma/client';
import {
  TransactionRequest,
  TransactionRequestProps,
} from '@/domain/aggregates/transaction-request';
import { ChainType, TxHash, EvmAddress, TokenAmount } from '@/domain/value-objects';
import { TransactionStatus } from '@/domain/enums';

export class TransactionRequestMapper {
  static toDomain(prisma: PrismaTransactionRequest): TransactionRequest {
    const props: TransactionRequestProps = {
      id: prisma.id,
      chainType: ChainType.create(prisma.chainType),
      sourceService: prisma.sourceService,
      sourceOrderId: prisma.sourceOrderId,
      fromAddress: EvmAddress.fromUnchecked(prisma.fromAddress),
      toAddress: EvmAddress.fromUnchecked(prisma.toAddress),
      value: TokenAmount.fromDecimal(prisma.value, 18),
      data: prisma.data ?? undefined,
      signedTx: prisma.signedTx ?? undefined,
      txHash: prisma.txHash ? TxHash.fromUnchecked(prisma.txHash) : undefined,
      status: prisma.status as TransactionStatus,
      gasLimit: prisma.gasLimit ?? undefined,
      gasPrice: prisma.gasPrice ?? undefined,
      nonce: prisma.nonce ?? undefined,
      errorMessage: prisma.errorMessage ?? undefined,
      retryCount: prisma.retryCount,
      createdAt: prisma.createdAt,
      updatedAt: prisma.updatedAt,
    };

    return TransactionRequest.reconstitute(props);
  }

  static toPersistence(
    domain: TransactionRequest,
  ): Omit<PrismaTransactionRequest, 'id' | 'createdAt' | 'updatedAt'> & { id?: bigint } {
    return {
      id: domain.id,
      chainType: domain.chainType.toString(),
      sourceService: domain.sourceService,
      sourceOrderId: domain.sourceOrderId,
      fromAddress: domain.fromAddress.toString(),
      toAddress: domain.toAddress.toString(),
      value: domain.value.toDecimal(),
      data: domain.data ?? null,
      signedTx: domain.signedTx ?? null,
      txHash: domain.txHash?.toString() ?? null,
      status: domain.status,
      gasLimit: domain.gasLimit ?? null,
      gasPrice: domain.gasPrice ?? null,
      nonce: domain.nonce ?? null,
      errorMessage: domain.errorMessage ?? null,
      retryCount: domain.retryCount,
    };
  }
}
