import Decimal from 'decimal.js';
import { UserId, AssetType, LedgerEntryType, Money } from '@/domain/value-objects';

export class LedgerEntry {
  private readonly _id: bigint;
  private readonly _accountSequence: string;  // 跨服务关联标识 (全局唯一业务ID)
  private readonly _userId: UserId;           // 保留兼容
  private readonly _entryType: LedgerEntryType;
  private readonly _amount: Money;
  private readonly _balanceAfter: Money | null;
  private readonly _refOrderId: string | null;
  private readonly _refTxHash: string | null;
  private readonly _memo: string | null;
  private readonly _payloadJson: Record<string, unknown> | null;
  private readonly _createdAt: Date;

  private constructor(
    id: bigint,
    accountSequence: string,
    userId: UserId,
    entryType: LedgerEntryType,
    amount: Money,
    balanceAfter: Money | null,
    refOrderId: string | null,
    refTxHash: string | null,
    memo: string | null,
    payloadJson: Record<string, unknown> | null,
    createdAt: Date,
  ) {
    this._id = id;
    this._accountSequence = accountSequence;
    this._userId = userId;
    this._entryType = entryType;
    this._amount = amount;
    this._balanceAfter = balanceAfter;
    this._refOrderId = refOrderId;
    this._refTxHash = refTxHash;
    this._memo = memo;
    this._payloadJson = payloadJson;
    this._createdAt = createdAt;
  }

  // Getters
  get id(): bigint { return this._id; }
  get accountSequence(): string { return this._accountSequence; }
  get userId(): UserId { return this._userId; }
  get entryType(): LedgerEntryType { return this._entryType; }
  get amount(): Money { return this._amount; }
  get assetType(): string { return this._amount.currency; }
  get balanceAfter(): Money | null { return this._balanceAfter; }
  get refOrderId(): string | null { return this._refOrderId; }
  get refTxHash(): string | null { return this._refTxHash; }
  get memo(): string | null { return this._memo; }
  get payloadJson(): Record<string, unknown> | null { return this._payloadJson; }
  get createdAt(): Date { return this._createdAt; }

  static create(params: {
    accountSequence: string;
    userId: UserId;
    entryType: LedgerEntryType;
    amount: Money;
    balanceAfter?: Money;
    refOrderId?: string;
    refTxHash?: string;
    memo?: string;
    payloadJson?: Record<string, unknown>;
  }): LedgerEntry {
    return new LedgerEntry(
      BigInt(0), // Will be set by database
      params.accountSequence,
      params.userId,
      params.entryType,
      params.amount,
      params.balanceAfter ?? null,
      params.refOrderId ?? null,
      params.refTxHash ?? null,
      params.memo ?? null,
      params.payloadJson ?? null,
      new Date(),
    );
  }

  static reconstruct(params: {
    id: bigint;
    accountSequence: string;
    userId: bigint;
    entryType: string;
    amount: Decimal;
    assetType: string;
    balanceAfter: Decimal | null;
    refOrderId: string | null;
    refTxHash: string | null;
    memo: string | null;
    payloadJson: Record<string, unknown> | null;
    createdAt: Date;
  }): LedgerEntry {
    return new LedgerEntry(
      params.id,
      params.accountSequence,
      UserId.create(params.userId),
      params.entryType as LedgerEntryType,
      Money.signed(params.amount, params.assetType), // Use signed() to allow negative amounts for deductions
      params.balanceAfter ? Money.create(params.balanceAfter, params.assetType) : null,
      params.refOrderId,
      params.refTxHash,
      params.memo,
      params.payloadJson,
      params.createdAt,
    );
  }
}
