import { Controller, Get, Post, Body, Param, Req, Logger, BadRequestException, HttpException, HttpStatus } from '@nestjs/common';
import { ApiTags, ApiOperation, ApiBearerAuth, ApiParam } from '@nestjs/swagger';
import { ConfigService } from '@nestjs/config';

// walletName → poolType 映射
interface PoolMapping {
  blockchainPoolType: string; // blockchain-service 使用的类型 (BURN_POOL / MINING_POOL)
  walletPoolType: string;     // wallet-service 使用的类型 (SHARE_POOL_A / SHARE_POOL_B)
  name: string;
}

@ApiTags('Pool Accounts')
@ApiBearerAuth()
@Controller('admin/pool-accounts')
export class PoolAccountController {
  private readonly logger = new Logger(PoolAccountController.name);
  private readonly walletServiceUrl: string;
  private readonly blockchainServiceUrl: string;
  private readonly walletNameMap: Record<string, PoolMapping>;

  constructor(private readonly configService: ConfigService) {
    this.walletServiceUrl = this.configService.get<string>(
      'MINING_WALLET_SERVICE_URL',
      'http://localhost:3025',
    );
    this.blockchainServiceUrl = this.configService.get<string>(
      'MINING_BLOCKCHAIN_SERVICE_URL',
      'http://localhost:3020',
    );

    // 从环境变量构建 walletName → poolType 映射
    const burnPoolUsername = this.configService.get<string>('BURN_POOL_WALLET_USERNAME', '');
    const miningPoolUsername = this.configService.get<string>('MINING_POOL_WALLET_USERNAME', '');

    this.walletNameMap = {};
    if (burnPoolUsername) {
      this.walletNameMap[burnPoolUsername] = {
        blockchainPoolType: 'BURN_POOL',
        walletPoolType: 'SHARE_POOL_A',
        name: '100亿销毁池',
      };
    }
    if (miningPoolUsername) {
      this.walletNameMap[miningPoolUsername] = {
        blockchainPoolType: 'MINING_POOL',
        walletPoolType: 'SHARE_POOL_B',
        name: '200万挖矿池',
      };
    }

    this.logger.log(
      `Pool account proxy initialized: walletService=${this.walletServiceUrl}, blockchainService=${this.blockchainServiceUrl}, pools=${Object.keys(this.walletNameMap).join(',')}`,
    );
  }

  @Get()
  @ApiOperation({ summary: '获取已配置的池账户列表' })
  async listPoolAccounts() {
    return Object.entries(this.walletNameMap).map(([walletName, info]) => ({
      walletName,
      name: info.name,
      walletPoolType: info.walletPoolType,
      blockchainPoolType: info.blockchainPoolType,
    }));
  }

  @Get(':walletName/balance')
  @ApiOperation({ summary: '获取池账户余额（代理到 wallet-service + blockchain-service）' })
  @ApiParam({ name: 'walletName', description: '池钱包名称（MPC用户名）' })
  async getPoolAccountBalance(@Param('walletName') walletName: string) {
    const poolInfo = this.walletNameMap[walletName];
    if (!poolInfo) {
      throw new BadRequestException(`Unknown wallet name: ${walletName}`);
    }

    // 并行调用 wallet-service 和 blockchain-service
    const [walletResponse, blockchainResponse] = await Promise.all([
      fetch(`${this.walletServiceUrl}/api/v2/pool-accounts/${poolInfo.walletPoolType}`).catch((err) => {
        this.logger.error(`Failed to fetch wallet balance: ${err.message}`);
        return null;
      }),
      fetch(`${this.blockchainServiceUrl}/api/v1/transfer/pool-accounts/${poolInfo.blockchainPoolType}/wallet-info`).catch((err) => {
        this.logger.error(`Failed to fetch blockchain wallet info: ${err.message}`);
        return null;
      }),
    ]);

    // 从 wallet-service 获取链下余额
    let balance = '0';
    let lastUpdated: string | undefined;
    if (walletResponse && walletResponse.ok) {
      const walletResult = await walletResponse.json();
      const data = walletResult.data || walletResult;
      balance = data.balance?.toString() || '0';
      lastUpdated = data.updatedAt;
    }

    // 从 blockchain-service 获取钱包地址和链上余额
    let walletAddress = '';
    let onChainBalance = '0';
    if (blockchainResponse && blockchainResponse.ok) {
      const blockchainResult = await blockchainResponse.json();
      const data = blockchainResult.data || blockchainResult;
      walletAddress = data.address || '';
      onChainBalance = data.balance || '0';
    }

    return {
      walletName,
      walletAddress,
      balance,
      availableBalance: balance,
      frozenBalance: '0',
      onChainBalance,
      threshold: '0',
      lastUpdated,
    };
  }

  @Post(':walletName/blockchain-withdraw')
  @ApiOperation({ summary: '池账户区块链提现（代理到 blockchain-service + wallet-service）' })
  @ApiParam({ name: 'walletName', description: '池钱包名称（MPC用户名）' })
  async poolAccountBlockchainWithdraw(
    @Param('walletName') walletName: string,
    @Body() body: { toAddress: string; amount: string },
  ) {
    const poolInfo = this.walletNameMap[walletName];
    if (!poolInfo) {
      throw new BadRequestException(`Unknown wallet name: ${walletName}`);
    }

    if (!body.toAddress || !body.amount) {
      throw new BadRequestException('toAddress and amount are required');
    }

    this.logger.log(
      `[withdraw] ${poolInfo.name}: ${body.amount} fUSDT to ${body.toAddress}`,
    );

    // Step 1: 通过 blockchain-service 执行区块链转账
    let blockchainData: any;
    try {
      const blockchainResponse = await fetch(
        `${this.blockchainServiceUrl}/api/v1/transfer/pool-account`,
        {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            poolType: poolInfo.blockchainPoolType,
            toAddress: body.toAddress,
            amount: body.amount,
          }),
        },
      );

      const blockchainResult = await blockchainResponse.json();
      blockchainData = blockchainResult.data || blockchainResult;

      if (!blockchainResponse.ok || !blockchainData.success) {
        this.logger.error(`[withdraw] Blockchain transfer failed: ${blockchainData.error}`);
        throw new HttpException(
          blockchainData.error || '区块链转账失败',
          blockchainResponse.status || HttpStatus.INTERNAL_SERVER_ERROR,
        );
      }
    } catch (error) {
      if (error instanceof HttpException) throw error;
      this.logger.error(`[withdraw] Failed to call blockchain service: ${error}`);
      throw new HttpException(
        `区块链服务调用失败: ${error instanceof Error ? error.message : error}`,
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }

    // Step 2: 在 wallet-service 记录提现（扣减余额 + 分类账）
    try {
      const walletResponse = await fetch(
        `${this.walletServiceUrl}/api/v2/pool-accounts/blockchain-withdraw`,
        {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            poolType: poolInfo.walletPoolType,
            amount: body.amount,
            txHash: blockchainData.txHash,
            toAddress: body.toAddress,
            blockNumber: blockchainData.blockNumber?.toString(),
          }),
        },
      );

      if (!walletResponse.ok) {
        const errResult = await walletResponse.json().catch(() => ({}));
        this.logger.error(
          `[withdraw] Failed to record withdrawal in wallet-service: ${JSON.stringify(errResult)}`,
        );
      }
    } catch (error) {
      // 区块链转账已成功，wallet-service 记录失败不影响最终结果
      this.logger.error(`[withdraw] Failed to record withdrawal in wallet-service: ${error}`);
    }

    this.logger.log(
      `[withdraw] Success: ${poolInfo.name}, txHash=${blockchainData.txHash}`,
    );

    return {
      success: true,
      message: '提现成功',
      txHash: blockchainData.txHash,
      blockNumber: blockchainData.blockNumber,
    };
  }

  @Post(':walletName/centralized-deposit')
  @ApiOperation({ summary: '池账户中心化充值（管理员手动调整余额）' })
  @ApiParam({ name: 'walletName', description: '池钱包名称（MPC用户名）' })
  async centralizedDeposit(
    @Param('walletName') walletName: string,
    @Body() body: { amount: string },
    @Req() req: any,
  ) {
    const poolInfo = this.walletNameMap[walletName];
    if (!poolInfo) {
      throw new BadRequestException(`Unknown wallet name: ${walletName}`);
    }

    if (!body.amount || parseFloat(body.amount) <= 0) {
      throw new BadRequestException('amount must be greater than 0');
    }

    const adminId = req.admin?.id || 'admin';
    this.logger.log(`[centralized-deposit] ${poolInfo.name}: ${body.amount} by admin ${adminId}`);

    try {
      const walletResponse = await fetch(
        `${this.walletServiceUrl}/api/v2/pool-accounts/centralized-deposit`,
        {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            poolType: poolInfo.walletPoolType,
            amount: body.amount,
            adminId: String(adminId),
          }),
        },
      );

      if (!walletResponse.ok) {
        const errResult = await walletResponse.json().catch(() => ({}));
        throw new HttpException(
          errResult.message || '中心化充值失败',
          walletResponse.status || HttpStatus.INTERNAL_SERVER_ERROR,
        );
      }

      return { success: true, message: `${poolInfo.name}充值成功` };
    } catch (error) {
      if (error instanceof HttpException) throw error;
      this.logger.error(`[centralized-deposit] Failed: ${error}`);
      throw new HttpException(
        `中心化充值失败: ${error instanceof Error ? error.message : error}`,
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }
}
