import { BadRequestException, Injectable } from '@nestjs/common';
import { DEFAULT_INITIAL_WHALE_COINS, EarnWalletResult, SpendWalletResult, WalletBalancePayload } from './user_wallets.service';
import { UserWallets } from './user_wallets.entity';
import { WalletTransactions } from './wallet_transactions.entity';

@Injectable()
export class UserWalletsMemoryService {
  private wallets: Map<bigint, UserWallets> = new Map();
  private transactions: WalletTransactions[] = [];
  private currentWalletId: bigint = BigInt(1);
  private currentTransactionId: bigint = BigInt(1);

  async ensureWallet(userId: bigint): Promise<UserWallets> {
    const existing = this.wallets.get(userId);
    if (existing) {
      return existing;
    }

    const wallet = new UserWallets();
    wallet.id = this.currentWalletId++;
    wallet.user_id = userId;
    wallet.balance = DEFAULT_INITIAL_WHALE_COINS;
    wallet.created_at = new Date();
    wallet.updated_at = new Date();
    this.wallets.set(userId, wallet);
    await this.createTransaction(userId, 'grant', DEFAULT_INITIAL_WHALE_COINS, wallet.balance, 'registration', 'initial_wallet', '新用户初始鲸币');
    return wallet;
  }

  async getBalance(userId: bigint): Promise<WalletBalancePayload> {
    const wallet = await this.ensureWallet(userId);
    return {
      user_id: userId.toString(),
      balance: wallet.balance,
      currency: 'whale_coin',
    };
  }

  async spend(userId: bigint, amount: number, referenceType: string, referenceId: string, note?: string): Promise<SpendWalletResult> {
    if (!Number.isInteger(amount) || amount < 0) {
      throw new BadRequestException('鲸币消费数量不正确');
    }

    const wallet = await this.ensureWallet(userId);
    if (wallet.balance < amount) {
      throw new BadRequestException('鲸币余额不足');
    }

    wallet.balance -= amount;
    wallet.updated_at = new Date();
    const transaction = await this.createTransaction(userId, 'spend', -amount, wallet.balance, referenceType, referenceId, note || '');
    return {
      wallet,
      transaction,
    };
  }

  async earn(userId: bigint, amount: number, referenceType: string, referenceId: string, note?: string): Promise<EarnWalletResult> {
    if (!Number.isInteger(amount) || amount < 0) {
      throw new BadRequestException('鲸币收入数量不正确');
    }

    const wallet = await this.ensureWallet(userId);
    wallet.balance += amount;
    wallet.updated_at = new Date();
    const transaction = await this.createTransaction(userId, 'earn', amount, wallet.balance, referenceType, referenceId, note || '');
    return {
      wallet,
      transaction,
    };
  }

  private async createTransaction(
    userId: bigint,
    type: string,
    amount: number,
    balanceAfter: number,
    referenceType: string,
    referenceId: string,
    note: string,
  ): Promise<WalletTransactions> {
    const transaction = new WalletTransactions();
    transaction.id = this.currentTransactionId++;
    transaction.user_id = userId;
    transaction.type = type;
    transaction.amount = amount;
    transaction.balance_after = balanceAfter;
    transaction.reference_type = referenceType;
    transaction.reference_id = referenceId;
    transaction.note = note || null;
    transaction.created_at = new Date();
    this.transactions.push(transaction);
    return transaction;
  }
}
