#!/usr/bin/env tsx
/**
 * Redis Connection Diagnostic Tool
 * Tests Redis connectivity with detailed error reporting
 */

import {createClient} from 'redis';

async function testRedisConnection() {
  const redisUrl = process.env.REDIS_URL || 'redis://localhost:6379';
  const redisPassword = process.env.REDIS_PASSWORD;

  console.log('🔍 Redis Connection Diagnostics');
  console.log('================================');
  console.log('Redis URL:', redisUrl);
  console.log('Password set:', redisPassword ? 'Yes (****)' : 'No');
  console.log('');

  // Parse URL to extract host and port
  try {
    const url = new URL(redisUrl);
    console.log('📋 Connection Details:');
    console.log('  Protocol:', url.protocol);
    console.log('  Host:', url.hostname);
    console.log('  Port:', url.port || '6379');
    console.log('  Username:', url.username || '(none)');
    console.log('');
  } catch (e) {
    console.error('❌ Invalid Redis URL format');
    process.exit(1);
  }

  let redisClient = null;
  let testsPassed = 0;
  let testsFailed = 0;

  try {
    console.log('⏳ Test 1: Creating Redis client...');
    const redisConfig: any = { 
      url: redisUrl,
      socket: {
        connectTimeout: 5000,
        reconnectStrategy: false
      }
    };
    
    if (redisPassword) {
      redisConfig.password = redisPassword;
    }
    
    redisClient = createClient(redisConfig);
    console.log('✅ Redis client created successfully');
    testsPassed++;
    console.log('');

    // Set up event listeners for diagnostics
    redisClient.on('error', (err) => {
      console.error('❌ Redis client error:', err.message);
    });

    redisClient.on('connect', () => {
      console.log('🔌 Connected to Redis');
    });

    redisClient.on('ready', () => {
      console.log('✅ Redis client ready');
    });

    console.log('⏳ Test 2: Connecting to Redis...');
    const connectStart = Date.now();
    await redisClient.connect();
    const connectTime = Date.now() - connectStart;
    console.log(`✅ Connected successfully in ${connectTime}ms`);
    testsPassed++;
    console.log('');

    console.log('⏳ Test 3: Testing PING command...');
    const pingStart = Date.now();
    const pong = await redisClient.ping();
    const pingTime = Date.now() - pingStart;
    console.log(`✅ PING successful: ${pong} (${pingTime}ms)`);
    testsPassed++;
    console.log('');

    console.log('⏳ Test 4: Testing SET command...');
    const testKey = 'diagnostic-test-key';
    const testValue = JSON.stringify({ 
      timestamp: Date.now(), 
      test: true,
      message: 'Diagnostic test from Web3Proxy'
    });
    await redisClient.set(testKey, testValue, { EX: 10 });
    console.log('✅ SET command successful');
    testsPassed++;
    console.log('');

    console.log('⏳ Test 5: Testing GET command...');
    const retrievedValue = await redisClient.get(testKey);
    if (retrievedValue) {
      const parsed = JSON.parse(retrievedValue);
      console.log('✅ GET command successful');
      console.log('   Retrieved value:', parsed);
      testsPassed++;
    } else {
      console.error('❌ GET command returned null');
      testsFailed++;
    }
    console.log('');

    console.log('⏳ Test 6: Testing DEL command...');
    await redisClient.del(testKey);
    console.log('✅ DEL command successful');
    testsPassed++;
    console.log('');

    console.log('⏳ Test 7: Getting Redis server info...');
    const info = await redisClient.info('server');
    const serverInfo = info.split('\r\n').reduce((acc, line) => {
      const [key, value] = line.split(':');
      if (key && value) {
        acc[key] = value;
      }
      return acc;
    }, {} as Record<string, string>);

    console.log('✅ Server info retrieved:');
    console.log(`   Redis version: ${serverInfo.redis_version}`);
    console.log(`   Uptime: ${serverInfo.uptime_in_seconds} seconds`);
    console.log(`   Connected clients: ${serverInfo.connected_clients}`);
    console.log(`   Used memory: ${serverInfo.used_memory_human}`);
    testsPassed++;
    console.log('');

  } catch (error) {
    console.error('');
    console.error('❌ Test failed with error:');
    console.error('   Type:', error instanceof Error ? error.constructor.name : 'Unknown');
    console.error('   Message:', error instanceof Error ? error.message : 'Unknown error');
    
    if (error instanceof Error && error.stack) {
      console.error('');
      console.error('Stack trace:');
      console.error(error.stack);
    }
    testsFailed++;
  } finally {
    if (redisClient && redisClient.isOpen) {
      try {
        console.log('⏳ Closing connection...');
        await redisClient.quit();
        console.log('✅ Connection closed successfully');
      } catch (closeError) {
        console.error('❌ Error closing connection:', closeError);
      }
    }
  }

  console.log('');
  console.log('================================');
  console.log('📊 Test Summary:');
  console.log(`   Passed: ${testsPassed}`);
  console.log(`   Failed: ${testsFailed}`);
  console.log('');

  if (testsFailed > 0) {
    console.log('❌ Redis connection tests failed');
    console.log('');
    console.log('💡 Troubleshooting tips:');
    console.log('1. Verify Redis is running: `redis-cli ping`');
    console.log('2. Check Redis host is reachable: `ping redis.kai.managing.live`');
    console.log('3. Check port is open: `nc -zv redis.kai.managing.live 6379`');
    console.log('4. Verify Redis bind address (should be 0.0.0.0, not 127.0.0.1)');
    console.log('5. Check firewall rules allow port 6379');
    console.log('6. Verify password is correct');
    console.log('7. Check Redis logs for connection attempts');
    console.log('');
    process.exit(1);
  } else {
    console.log('✅ All tests passed! Redis is working correctly.');
    process.exit(0);
  }
}

// Run the diagnostic
testRedisConnection().catch((error) => {
  console.error('Unexpected error:', error);
  process.exit(1);
});

