/**
 * Deposit Controller
 *
 * Provides deposit-related endpoints for the mobile app.
 * Queries on-chain USDT balances for user's monitored addresses.
 */

import { Controller, Get, Logger, Inject, UseGuards, Req } from '@nestjs/common';
import { ApiTags, ApiOperation, ApiResponse, ApiBearerAuth } from '@nestjs/swagger';
import { Request } from 'express';
import { BalanceQueryService } from '@/application/services/balance-query.service';
import { ChainTypeEnum } from '@/domain/enums';
import {
  IMonitoredAddressRepository,
  MONITORED_ADDRESS_REPOSITORY,
} from '@/domain/repositories/monitored-address.repository.interface';
import { JwtAuthGuard } from '@/shared/guards/jwt-auth.guard';

interface JwtPayload {
  userId: string;
  accountSequence: string;
  deviceId: string;
}

interface UsdtBalanceDto {
  chainType: string;
  address: string;
  balance: string;
  rawBalance: string;
  decimals: number;
}

interface DepositBalancesResponseDto {
  kava: UsdtBalanceDto | null;
  bsc: UsdtBalanceDto | null;
}

@ApiTags('Deposit')
@Controller('deposit')
export class DepositController {
  private readonly logger = new Logger(DepositController.name);

  constructor(
    private readonly balanceService: BalanceQueryService,
    @Inject(MONITORED_ADDRESS_REPOSITORY)
    private readonly monitoredAddressRepo: IMonitoredAddressRepository,
  ) {}

  @Get('balances')
  @UseGuards(JwtAuthGuard)
  @ApiBearerAuth()
  @ApiOperation({ summary: '查询用户 USDT 余额' })
  @ApiResponse({ status: 200, description: '余额信息' })
  async getBalances(@Req() req: Request): Promise<DepositBalancesResponseDto> {
    const user = (req as Request & { user: JwtPayload }).user;
    const userId = BigInt(user.userId);

    this.logger.log(`Querying deposit balances for user ${userId}`);

    // Get user's monitored addresses
    const addresses = await this.monitoredAddressRepo.findByUserId(userId);

    const response: DepositBalancesResponseDto = {
      kava: null,
      bsc: null,
    };

    // Query balance for each chain
    for (const addr of addresses) {
      try {
        const chainType = addr.chainType;
        const addressStr = addr.address.toString();
        const chainTypeStr = chainType.toString();

        const balance = await this.balanceService.getBalance(chainType, addressStr);

        const balanceDto: UsdtBalanceDto = {
          chainType: chainTypeStr,
          address: addressStr,
          balance: balance.usdtBalance,
          rawBalance: balance.usdtRawBalance,
          decimals: balance.usdtDecimals,
        };

        if (chainTypeStr === ChainTypeEnum.KAVA) {
          response.kava = balanceDto;
        } else if (chainTypeStr === ChainTypeEnum.BSC) {
          response.bsc = balanceDto;
        }
      } catch (error) {
        this.logger.error(`Error querying balance for ${addr.chainType}:${addr.address}`, error);
      }
    }

    this.logger.log(
      `Balance query complete for user ${userId}: ` +
      `KAVA=${response.kava?.balance || '0'}, BSC=${response.bsc?.balance || '0'}`,
    );

    return response;
  }
}
