import { Injectable } from '@nestjs/common';
import { Prisma } from '@prisma/client';
import { Decimal } from '@prisma/client/runtime/library';
import { WalletService } from './wallet.service';

type TxClient = Prisma.TransactionClient;

@Injectable()
export class FundsPostingService {
  constructor(private wallet: WalletService) {}

  deposit(command: {
    userId: bigint;
    amount: Decimal | number;
    operatorId: bigint;
    remark?: string;
    referenceId?: string;
    transactionType?: string;
    businessKey?: string;
    tx?: TxClient;
  }) {
    return this.wallet.deposit(
      command.userId,
      command.amount,
      command.operatorId,
      command.remark,
      command.referenceId,
      command.transactionType ?? 'MANUAL_DEPOSIT',
      command.tx,
      command.businessKey,
    );
  }

  withdraw(command: {
    userId: bigint;
    amount: Decimal | number;
    operatorId: bigint;
    remark?: string;
    referenceId?: string;
    transactionType?: string;
    referenceType?: string;
    businessKey?: string;
    tx?: TxClient;
  }) {
    return this.wallet.withdraw(
      command.userId,
      command.amount,
      command.operatorId,
      command.remark,
      command.referenceId,
      command.transactionType ?? 'MANUAL_WITHDRAW',
      command.tx,
      command.businessKey,
      command.referenceType,
    );
  }

  freezeBet(command: {
    userId: bigint;
    stake: Decimal | number;
    betNo: string;
    tx?: TxClient;
  }) {
    return this.wallet.freezeForBet(
      command.userId,
      command.stake,
      command.betNo,
      command.tx,
      `bet:${command.betNo}:freeze`,
    );
  }

  settleBet(command: {
    userId: bigint;
    stake: Decimal;
    payout: Decimal;
    betNo: string;
    batchNo: string;
    result: 'WIN' | 'LOSE' | 'PUSH' | 'VOID' | 'HALF_WIN' | 'HALF_LOSE';
    tx?: TxClient;
  }) {
    return this.wallet.settleBet(
      command.userId,
      command.stake,
      command.payout,
      command.betNo,
      command.result,
      command.tx,
      `settle:${command.batchNo}:${command.betNo}`,
    );
  }

  voidBet(command: {
    userId: bigint;
    stake: Decimal;
    betNo: string;
    businessKey: string;
    tx?: TxClient;
  }) {
    return this.wallet.settleBet(
      command.userId,
      command.stake,
      command.stake,
      command.betNo,
      'VOID',
      command.tx,
      command.businessKey,
    );
  }

  applyResettleDelta(command: {
    userId: bigint;
    delta: Decimal;
    betNo: string;
    batchNo: string;
    tx?: TxClient;
  }) {
    return this.wallet.applyResettleDelta(
      command.userId,
      command.delta,
      command.betNo,
      command.tx,
      `resettle:${command.batchNo}:${command.betNo}`,
    );
  }
}
