import { DepositTransaction as PrismaDepositTransaction } from '@prisma/client';
import {
  DepositTransaction,
  DepositTransactionProps,
} from '@/domain/aggregates/deposit-transaction';
import { ChainType, TxHash, EvmAddress, TokenAmount, BlockNumber } from '@/domain/value-objects';
import { DepositStatus } from '@/domain/enums';

export class DepositTransactionMapper {
  /**
   * Map from Prisma to Domain (only for USER deposits)
   * System account deposits are handled separately
   */
  static toDomain(prisma: PrismaDepositTransaction): DepositTransaction {
    // For USER deposits, accountSequence and userId must exist
    if (!prisma.accountSequence || !prisma.userId) {
      throw new Error(`DepositTransaction ${prisma.id} missing accountSequence or userId`);
    }

    // 使用 amountFormatted 重建 TokenAmount
    // amountFormatted 已经是正确的人类可读格式（如 1000000.00000000）
    // 用 decimals=8 与 toFixed(8) 保持一致，确保 toFixed(8) 返回相同的值
    const amount = TokenAmount.fromFormatted(prisma.amountFormatted.toString(), 8);

    const props: DepositTransactionProps = {
      id: prisma.id,
      chainType: ChainType.create(prisma.chainType),
      txHash: TxHash.fromUnchecked(prisma.txHash),
      fromAddress: EvmAddress.fromUnchecked(prisma.fromAddress),
      toAddress: EvmAddress.fromUnchecked(prisma.toAddress),
      tokenContract: EvmAddress.fromUnchecked(prisma.tokenContract),
      amount,
      blockNumber: BlockNumber.create(prisma.blockNumber),
      blockTimestamp: prisma.blockTimestamp,
      logIndex: prisma.logIndex,
      confirmations: prisma.confirmations,
      status: prisma.status as DepositStatus,
      addressId: prisma.addressId,
      accountSequence: prisma.accountSequence,
      userId: prisma.userId,
      notifiedAt: prisma.notifiedAt ?? undefined,
      notifyAttempts: prisma.notifyAttempts,
      lastNotifyError: prisma.lastNotifyError ?? undefined,
      createdAt: prisma.createdAt,
      updatedAt: prisma.updatedAt,
    };

    return DepositTransaction.reconstitute(props);
  }

  static toPersistence(
    domain: DepositTransaction,
  ): Omit<PrismaDepositTransaction, 'id' | 'createdAt' | 'updatedAt'> & { id?: bigint } {
    return {
      id: domain.id,
      chainType: domain.chainType.toString(),
      txHash: domain.txHash.toString(),
      fromAddress: domain.fromAddress.toString(),
      toAddress: domain.toAddress.toString(),
      tokenContract: domain.tokenContract.toString(),
      amount: domain.amount.toDecimal(),
      amountFormatted: domain.amount.toFormattedDecimal(),
      blockNumber: domain.blockNumber.value,
      blockTimestamp: domain.blockTimestamp,
      logIndex: domain.logIndex,
      confirmations: domain.confirmations,
      status: domain.status,
      addressId: domain.addressId,
      addressType: 'USER',
      accountSequence: domain.accountSequence,
      userId: domain.userId,
      systemAccountType: null,
      systemAccountId: null,
      notifiedAt: domain.notifiedAt ?? null,
      notifyAttempts: domain.notifyAttempts,
      lastNotifyError: domain.lastNotifyError ?? null,
    };
  }
}
