import { NestFactory } from '@nestjs/core';
import { ValidationPipe, Logger } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
import { MicroserviceOptions, Transport } from '@nestjs/microservices';
import { AppModule } from './app.module';
import { Erc20TransferService } from './domain/services/erc20-transfer.service';
import { ChainTypeEnum } from './domain/enums';

async function bootstrap() {
  const logger = new Logger('Bootstrap');

  const app = await NestFactory.create(AppModule);

  const configService = app.get(ConfigService);

  // 全局验证管道
  app.useGlobalPipes(
    new ValidationPipe({
      whitelist: true,
      transform: true,
      forbidNonWhitelisted: true,
    }),
  );

  // CORS
  app.enableCors();

  // 全局 API 前缀
  const apiPrefix = configService.get<string>('app.apiPrefix', 'api/v1');
  app.setGlobalPrefix(apiPrefix);

  // Swagger 文档
  const swaggerConfig = new DocumentBuilder()
    .setTitle('Mining Blockchain Service API')
    .setDescription('Mining 区块链服务 - C2C Bot dUSDT 转账')
    .setVersion('1.0')
    .addTag('Health', '健康检查')
    .addTag('Transfer', 'dUSDT 转账')
    .build();

  const document = SwaggerModule.createDocument(app, swaggerConfig);
  SwaggerModule.setup('api', app, document);

  // Kafka 微服务（用于 MPC 签名通信）
  const kafkaBrokers = configService.get<string[]>('kafka.brokers') || ['localhost:9092'];
  const kafkaGroupId = configService.get<string>('kafka.groupId') || 'mining-blockchain-service-group';

  app.connectMicroservice<MicroserviceOptions>({
    transport: Transport.KAFKA,
    options: {
      client: {
        clientId: 'mining-blockchain-service',
        brokers: kafkaBrokers,
      },
      consumer: {
        groupId: kafkaGroupId,
      },
    },
  });

  // 启动微服务
  await app.startAllMicroservices();
  logger.log('Kafka microservice started for MPC signing');

  // 验证关键配置
  validateBlockchainConfig(configService, logger);

  // 启动 HTTP 服务
  const port = configService.get<number>('app.port', 3020);
  await app.listen(port);

  logger.log(`Mining Blockchain service is running on port ${port}`);
  logger.log(`Swagger docs available at http://localhost:${port}/api`);

  // 异步检查 fUSDT 注入钱包余额（不阻塞启动）
  checkInjectionWalletBalance(app, logger).catch(err => {
    logger.error('[STARTUP] Failed to check injection wallet balance', err);
  });
}

/**
 * 验证区块链关键配置
 * 如果缺少必要配置，输出明确的错误日志
 */
function validateBlockchainConfig(configService: ConfigService, logger: Logger) {
  const warnings: string[] = [];

  // eUSDT (积分股) 做市商钱包配置验证
  const eusdtMarketMakerAddress = configService.get<string>('blockchain.eusdtMarketMaker.walletAddress');
  const eusdtMarketMakerUsername = configService.get<string>('blockchain.eusdtMarketMaker.mpcUsername');

  logger.log(`[CONFIG] eUSDT (积分股) 做市商钱包配置:`);
  if (eusdtMarketMakerAddress) {
    logger.log(`  - 地址: ${eusdtMarketMakerAddress}`);
  } else {
    warnings.push('[CONFIG WARNING] EUSDT_MARKET_MAKER_ADDRESS 未配置！eUSDT 充值监控功能将不可用。');
  }
  if (!eusdtMarketMakerUsername) {
    warnings.push('[CONFIG WARNING] EUSDT_MARKET_MAKER_USERNAME 未配置！eUSDT 转账功能将不可用。');
  }

  // fUSDT (积分值) 做市商钱包配置验证
  const fusdtMarketMakerAddress = configService.get<string>('blockchain.fusdtMarketMaker.walletAddress');
  const fusdtMarketMakerUsername = configService.get<string>('blockchain.fusdtMarketMaker.mpcUsername');

  logger.log(`[CONFIG] fUSDT (积分值) 做市商钱包配置:`);
  if (fusdtMarketMakerAddress) {
    logger.log(`  - 地址: ${fusdtMarketMakerAddress}`);
  } else {
    warnings.push('[CONFIG WARNING] FUSDT_MARKET_MAKER_ADDRESS 未配置！fUSDT 充值监控功能将不可用。');
  }
  if (!fusdtMarketMakerUsername) {
    warnings.push('[CONFIG WARNING] FUSDT_MARKET_MAKER_USERNAME 未配置！fUSDT 转账功能将不可用。');
  }

  // C2C Bot 热钱包配置验证
  const c2cBotWalletAddress = configService.get<string>('C2C_BOT_WALLET_ADDRESS');
  const c2cBotWalletUsername = configService.get<string>('C2C_BOT_WALLET_USERNAME');

  logger.log(`[CONFIG] C2C Bot 热钱包配置:`);
  if (c2cBotWalletAddress) {
    logger.log(`  - 地址: ${c2cBotWalletAddress}`);
  } else {
    warnings.push('[CONFIG WARNING] C2C_BOT_WALLET_ADDRESS 未配置！C2C Bot 转账功能将不可用。');
  }
  if (!c2cBotWalletUsername) {
    warnings.push('[CONFIG WARNING] C2C_BOT_WALLET_USERNAME 未配置！C2C Bot MPC 签名功能将不可用。');
  }

  // fUSDT 注入钱包配置验证（认种自动转积分值到做市商）
  const fusdtInjectionAddress = configService.get<string>('FUSDT_INJECTION_WALLET_ADDRESS');
  const fusdtInjectionUsername = configService.get<string>('FUSDT_INJECTION_WALLET_USERNAME');

  logger.log(`[CONFIG] fUSDT 注入钱包配置（认种自动注入）:`);
  if (fusdtInjectionAddress) {
    logger.log(`  - 地址: ${fusdtInjectionAddress}`);
  } else {
    warnings.push('[CONFIG WARNING] FUSDT_INJECTION_WALLET_ADDRESS 未配置！认种自动 fUSDT 注入功能将不可用。');
  }
  if (!fusdtInjectionUsername) {
    warnings.push('[CONFIG WARNING] FUSDT_INJECTION_WALLET_USERNAME 未配置！认种自动 fUSDT 注入签名将不可用。');
  }

  // KAVA 代币合约配置日志
  const eUsdtContract = configService.get<string>('blockchain.kava.eUsdtContract');
  const fUsdtContract = configService.get<string>('blockchain.kava.fUsdtContract');
  const usdtContract = configService.get<string>('blockchain.kava.usdtContract');

  logger.log(`[CONFIG] KAVA 代币合约配置:`);
  logger.log(`  - eUSDT (积分股): ${eUsdtContract || '未配置'}`);
  logger.log(`  - fUSDT (积分值): ${fUsdtContract || '未配置'}`);
  logger.log(`  - dUSDT (绿积分): ${usdtContract || '未配置'}`);

  // 输出所有警告
  warnings.forEach(warning => logger.warn(warning));

  if (warnings.length > 0) {
    logger.warn(`[CONFIG] 发现 ${warnings.length} 个配置警告，部分功能将不可用！`);
  }
}

/**
 * 检查 fUSDT 注入钱包余额
 * 如果余额为 0，输出警告日志
 */
async function checkInjectionWalletBalance(app: any, logger: Logger) {
  try {
    const erc20Service = app.get(Erc20TransferService);
    const injectionAddress = erc20Service.getFusdtInjectionAddress();

    if (!injectionAddress) {
      logger.warn('[BALANCE] fUSDT 注入钱包未配置，跳过余额检查');
      return;
    }

    logger.log(`[BALANCE] 正在查询 fUSDT 注入钱包余额: ${injectionAddress}`);
    const balance = await erc20Service.getFusdtInjectionTokenBalance(ChainTypeEnum.KAVA);
    const balanceNum = parseFloat(balance);

    if (balanceNum === 0) {
      logger.warn(`[BALANCE] ⚠️  fUSDT 注入钱包余额为 0！地址: ${injectionAddress}`);
      logger.warn(`[BALANCE] ⚠️  认种自动注入将因余额不足而失败，请及时充值！`);
    } else {
      logger.log(`[BALANCE] fUSDT 注入钱包余额: ${balance} fUSDT`);
    }
  } catch (error) {
    logger.warn(`[BALANCE] 无法查询 fUSDT 注入钱包余额 (链可能未就绪): ${error instanceof Error ? error.message : error}`);
  }
}

bootstrap();
