/**
 * RPC Translator Service - Main Entry Point
 * ChainID 138 - Thirdweb compatibility with eth_sendTransaction support
 */

import { loadConfig } from './config';
import { HttpServer } from './servers/http-server';
import { WsServer } from './servers/ws-server';
import { BesuClient } from './clients/besu-client';
import { Web3SignerClient } from './clients/web3signer-client';
import { VaultClient } from './clients/vault-client';
import { NonceManager } from './services/nonce-manager';
import { RpcHandler } from './handlers/rpc-handler';
import { TxInterceptor } from './interceptors/tx-interceptor';
import Redis from 'ioredis';

async function main() {
  const config = loadConfig();

  console.log('Starting RPC Translator Service for ChainID', config.besu.chainId);
  console.log('HTTP Port:', config.server.httpPort);
  console.log('WebSocket Port:', config.server.wsPort);

  // Initialize Redis
  const redis = new Redis({
    host: config.redis.host,
    port: config.redis.port,
    password: config.redis.password,
    db: config.redis.db,
    retryStrategy: (times: number) => {
      const delay = Math.min(times * 50, 2000);
      return delay;
    },
  });

  redis.on('error', (err: Error) => {
    console.error('Redis connection error:', err);
  });

  redis.on('connect', () => {
    console.log('Redis connected');
  });

  // Initialize clients
  const besuClient = new BesuClient(config.besu);
  const web3SignerClient = new Web3SignerClient(config.web3signer);
  const vaultClient = new VaultClient(config.vault);
  const nonceManager = new NonceManager(redis, besuClient, config.redis.keyPrefix, config.besu.chainId);

  // Initialize Vault and load config
  try {
    await vaultClient.initialize();
    const vaultConfig = await vaultClient.getTranslatorConfig();
    
    // Merge vault config into policy
    if (vaultConfig.walletAllowlist && vaultConfig.walletAllowlist.length > 0) {
      config.policy.walletAllowlist = vaultConfig.walletAllowlist;
    }
    if (vaultConfig.maxGasLimit) {
      config.policy.maxGasLimit = BigInt(vaultConfig.maxGasLimit);
    }
    if (vaultConfig.maxGasPriceWei) {
      config.policy.maxGasPriceWei = BigInt(vaultConfig.maxGasPriceWei);
    }
    if (vaultConfig.minGasPriceWei) {
      config.policy.minGasPriceWei = BigInt(vaultConfig.minGasPriceWei);
    }
    
    console.log('Vault configuration loaded');
  } catch (error) {
    console.warn('Failed to load Vault config, using environment/defaults:', error);
  }

  // Initialize interceptor
  const txInterceptor = new TxInterceptor(
    besuClient,
    web3SignerClient,
    nonceManager,
    config.besu.chainId,
    config.policy
  );

  // Initialize RPC handler with Web3Signer client for smart interception
  const rpcHandler = new RpcHandler(
    besuClient,
    txInterceptor,
    config.besu.chainId,
    config.allowPrivateNetworkMethods,
    web3SignerClient
  );

  // Initialize servers
  const httpServer = new HttpServer(
    config.server.httpPort,
    rpcHandler,
    besuClient,
    web3SignerClient,
    vaultClient,
    redis
  );
  const wsServer = new WsServer(config.server.wsPort, rpcHandler, besuClient);

  // Start servers
  await httpServer.start();
  await wsServer.start();

  console.log('RPC Translator Service started successfully');
  console.log(`HTTP server listening on port ${config.server.httpPort}`);
  console.log(`WebSocket server listening on port ${config.server.wsPort}`);

  // Graceful shutdown
  process.on('SIGINT', async () => {
    console.log('\nReceived SIGINT, shutting down gracefully...');
    await httpServer.stop();
    await wsServer.stop();
    await besuClient.close();
    redis.disconnect();
    process.exit(0);
  });

  process.on('SIGTERM', async () => {
    console.log('\nReceived SIGTERM, shutting down gracefully...');
    await httpServer.stop();
    await wsServer.stop();
    await besuClient.close();
    redis.disconnect();
    process.exit(0);
  });
}

main().catch((error) => {
  console.error('Fatal error:', error);
  process.exit(1);
});
