import { execSync, spawn } from 'child_process';
import { existsSync } from 'fs';
import { join, basename } from 'path';
import { homedir } from 'os';
import { createInterface } from 'readline';
import * as net from 'net';
import { Logger } from '../utils/logger.js';
import { 
  storeCredentials, 
  getCredentials, 
  CREDENTIAL_KEYS, 
  isKeyringSupportAvailable,
  getCredentialSummary
} from '../utils/keyring.js';

export interface LudusConfig {
  adminUser: string;
  connectionMethod: 'wireguard' | 'ssh-tunnel';
  wireguardConfig?: string | undefined;  // Optional for SSH tunnel mode
  apiKey: string;
  sshHost: string;
  sshUser: string;
  sshAuthMethod: 'password' | 'key';
  sshPassword?: string | undefined;  // Optional for key-based auth
  sshKeyPath?: string | undefined;   // Optional for password auth
  sshKeyPassphrase?: string | undefined;  // Optional passphrase for password-protected keys
  ludusUrl?: string;
  verifySSL?: boolean;
}

export interface SetupResult {
  success: boolean;
  message: string;
  config?: LudusConfig;
  requiresRestart?: boolean;
}

export class InteractiveSetup {
  private logger: Logger;
  private rl: any;

  constructor(logger: Logger) {
    this.logger = logger;
    this.rl = createInterface({
      input: process.stdin,
      output: process.stderr  // Use stderr to avoid interfering with MCP protocol stdout
    });
  }

  /**
   * Secure prompt for sensitive data (hides input)
   */
  private async securePrompt(question: string): Promise<string> {
    // Simple fallback - just use regular prompt for now
    // The security benefit of hiding input is minimal for this use case
    return this.prompt(question);
  }

  private async prompt(question: string): Promise<string> {
    return new Promise((resolve) => {
      this.rl.question(question, (answer: string) => {
        resolve(answer.trim());
      });
    });
  }

  private checkWireGuardAvailable(): boolean {
    try {
      execSync('wg --version', { stdio: 'ignore' });
      return true;
    } catch {
      return false;
    }
  }

  private checkWireGuardConnectivity(): boolean {
    try {
      const result = execSync('wg show', { encoding: 'utf8' });
      return result.trim().length > 0;
    } catch {
      return false;
    }
  }

  private async connectWireGuard(configPath: string): Promise<boolean> {
    try {
      if (!existsSync(configPath)) {
        console.error(`WireGuard config file not found: ${configPath}`);
        return false;
      }

      // First check if WireGuard is already connected
      if (this.checkWireGuardConnectivity()) {
        console.error('WireGuard VPN already connected');
        return true;
      }

      // Check if interface already exists
      try {
        const interfaces = execSync('wg show interfaces', { encoding: 'utf8' });
        if (interfaces.trim().length > 0) {
          console.error('WireGuard interface already active');
          return true;
        }
      } catch (e) {
        // wg command might not be available, continue with connection attempt
      }

      // Try to connect to WireGuard - platform-specific approach
      const isWindows = process.platform === 'win32';
      
      if (isWindows) {
        // Windows: Use WireGuard GUI or service approach
        return await this.connectWireGuardWindows(configPath);
      } else {
        // Linux/Mac: Use wg-quick
        return await this.connectWireGuardUnix(configPath);
      }

    } catch (error: any) {
      console.error(`WireGuard connection failed: ${error.message}`);
      return false;
    }
  }

  // Helper function to execute WireGuard commands securely
  private async executeWireGuardCommand(command: string, args: string[]): Promise<string> {
    return new Promise((resolve, reject) => {
      const process = spawn(command, args, { 
        stdio: 'pipe', 
        shell: false 
      });
      
      let output = '';
      let error = '';
      
      process.stdout.on('data', (data) => output += data.toString());
      process.stderr.on('data', (data) => error += data.toString());
      
      process.on('close', (code) => {
        if (code === 0) {
          resolve(output);
        } else {
          reject(new Error(`Command failed with code ${code}: ${error}`));
        }
      });
      
      process.on('error', (err) => reject(err));
    });
  }

  private async connectWireGuardWindows(configPath: string): Promise<boolean> {
    try {
      console.error('Setting up WireGuard tunnel on Windows...');
      
      // Find WireGuard installation
      const wireguardPaths = [
        'C:\\Program Files\\WireGuard\\wireguard.exe',
        'C:\\Program Files (x86)\\WireGuard\\wireguard.exe'
      ];
      
      let wireguardPath = '';
      for (const path of wireguardPaths) {
        if (existsSync(path)) {
          wireguardPath = path;
          break;
        }
      }
      
      if (!wireguardPath) {
        console.error('WireGuard not found. Please install it first:');
        console.error('   Download from: https://www.wireguard.com/install/');
        console.error('   Or run: winget install WireGuard.WireGuard');
        return false;
      }
      
      // Extract tunnel name from config file path
      const tunnelName = basename(configPath, '.conf');
      
      // Stop existing tunnel if running
      try {
        console.error('Stopping existing WireGuard tunnel...');
        // Use spawn to prevent command injection
        const result = spawn(wireguardPath, ['/uninstalltunnelservice', tunnelName], { 
          stdio: 'pipe',
          shell: false
        });
        await new Promise<void>((resolve) => {
          result.on('close', () => resolve());
          result.on('error', () => resolve()); // Ignore errors for cleanup
        });
        console.error('Existing tunnel stopped');
      } catch (error) {
        // Tunnel might not exist, continue
        console.error(' No existing tunnel to stop');
      }
      
      // Install and start new tunnel
      try {
        console.error('Installing WireGuard tunnel service...');
        const result = await this.executeWireGuardCommand(wireguardPath, ['/installtunnelservice', configPath]);
        console.error('WireGuard tunnel service installed and started');
        
        // Wait a moment for tunnel to establish
        await new Promise(resolve => setTimeout(resolve, 3000));
        
        // Verify connection
        if (this.checkWireGuardConnectivity()) {
          console.error('WireGuard VPN connected successfully');
          return true;
        } else {
          console.error('WireGuard tunnel started but connectivity verification failed');
          console.error('This might be normal - the tunnel may need more time to establish');
          return true; // Return true since the service started successfully
        }
        
      } catch (error: any) {
        console.error(`Failed to install WireGuard tunnel service: ${error.message}`);
        return false;
      }
      
    } catch (error: any) {
      console.error(`Windows WireGuard connection failed: ${error.message}`);
      return false;
    }
  }

  /**
   * Stop WireGuard tunnel on Windows
   */
  private async stopWireGuardWindows(configPath: string): Promise<void> {
    try {
      const wireguardPaths = [
        'C:\\Program Files\\WireGuard\\wireguard.exe',
        'C:\\Program Files (x86)\\WireGuard\\wireguard.exe'
      ];
      
      let wireguardPath = '';
      for (const path of wireguardPaths) {
        if (existsSync(path)) {
          wireguardPath = path;
          break;
        }
      }
      
      if (wireguardPath) {
        const tunnelName = basename(configPath, '.conf');
        console.error('Stopping WireGuard tunnel...');
        
        try {
          await this.executeWireGuardCommand(wireguardPath, ['/uninstalltunnelservice', tunnelName]);
          console.error('WireGuard tunnel stopped');
        } catch (error) {
          console.error(' WireGuard tunnel was not running');
        }
      }
    } catch (error: any) {
      console.error(` Error stopping WireGuard tunnel: ${error.message}`);
    }
  }

  private async connectWireGuardUnix(configPath: string): Promise<boolean> {
    try {
      const result = await this.executeWireGuardCommand('wg-quick', ['up', configPath]);
      console.error('WireGuard VPN connected successfully');
      return true;
    } catch (error: any) {
      // Handle "already exists" error gracefully
      if (error.message.includes('already exists')) {
        console.error('WireGuard interface already active');
        return true;
      }
      throw error; // Re-throw other errors
    }
  }

  private async validateApiKey(apiKey: string, ludusUrl: string = 'https://198.51.100.1:8080'): Promise<boolean> {
    try {
      // Set the API key in environment for the command
      const env = { ...process.env, LUDUS_API_KEY: apiKey };
      
      // Test the API key by getting server info
      const result = spawn('ludus', ['--url', ludusUrl, 'version'], {
        env,
        stdio: 'pipe'
      });

      let stdout = '';
      let stderr = '';

      result.stdout.on('data', (data) => {
        stdout += data.toString();
      });

      result.stderr.on('data', (data) => {
        stderr += data.toString();
      });

      return new Promise((resolve) => {
        result.on('close', (code) => {
          // Check both stdout and stderr for success indicators
          const output = stdout + stderr;
          const success = code === 0 || 
                         output.includes('version') || 
                         output.includes('Ludus') ||
                         output.includes('server');
          
          if (success) {
            console.error(`API key validation successful`);
            resolve(true);
          } else {
            console.error(`API key validation failed. Code: ${code}`);
            console.error(`Output: ${output}`);
            resolve(false);
          }
        });

        result.on('error', (error) => {
          console.error(`API key validation error: ${error.message}`);
          resolve(false);
        });
      });
    } catch (error: any) {
      console.error(`API key validation failed: ${error.message}`);
      return false;
    }
  }

  private async testSshConnectivity(config: LudusConfig): Promise<boolean> {
    try {
      // Use ssh2 library (consistent with tunnel manager)
      const { Client } = await import('ssh2');
      const ssh = new Client();

      const sshConfig: any = {
        host: config.sshHost,
        username: config.sshUser,
        readyTimeout: 10000, // 10 second timeout
      };

      if (config.sshAuthMethod === 'key') {
        // Key-based authentication
        if (!config.sshKeyPath) {
          console.error('SSH key path is required for key authentication');
          return false;
        }
        
        const fs = await import('fs/promises');
        try {
          const privateKey = await fs.readFile(config.sshKeyPath);
          sshConfig.privateKey = privateKey;
          if (config.sshKeyPassphrase) {
            sshConfig.passphrase = config.sshKeyPassphrase;
          }
        } catch (keyError: any) {
          console.error(`Failed to read SSH private key: ${keyError.message}`);
          return false;
        }
      } else {
        // Password authentication
        sshConfig.password = config.sshPassword;
      }

      return new Promise((resolve) => {
        let resolved = false;
        
        const cleanup = () => {
          if (!resolved) {
            resolved = true;
            ssh.end();
          }
        };

        const timeout = setTimeout(() => {
          if (!resolved) {
            resolved = true;
            console.error('SSH connectivity test timed out');
            ssh.end();
            resolve(false);
          }
        }, 12000); // 12 second total timeout

        ssh.on('ready', () => {
          ssh.exec('echo "SSH test successful"', (err, stream) => {
            if (err) {
              clearTimeout(timeout);
              cleanup();
              console.error(`SSH command execution failed: ${err.message}`);
              resolve(false);
              return;
            }

            let output = '';
            stream.on('data', (data: Buffer) => {
              output += data.toString();
            });

            stream.on('close', (code: number) => {
              clearTimeout(timeout);
              cleanup();
              
              if (code === 0 && output.trim() === 'SSH test successful') {
                console.error('SSH connectivity test successful');
                resolve(true);
              } else {
                console.error(`SSH connectivity test failed with code: ${code}`);
                resolve(false);
              }
            });
          });
        });

        ssh.on('error', (error: any) => {
          clearTimeout(timeout);
          cleanup();
          console.error(`SSH connectivity test failed: ${error.message}`);
          resolve(false);
        });

        try {
          ssh.connect(sshConfig);
        } catch (connectError: any) {
          clearTimeout(timeout);
          cleanup();
          console.error(`SSH connectivity test error: ${connectError.message}`);
          resolve(false);
        }
      });
    } catch (error: any) {
      console.error(`SSH connectivity test error: ${error.message}`);
      return false;
    }
  }

  private async createSshTunnel(config: LudusConfig): Promise<boolean> {
    try {
      console.error('📡 Creating SSH tunnels for ports 8080 and 8081...');
      
      // Use the existing SSH tunnel manager instead of duplicating tunnel logic
      const { LudusSSHTunnelManager } = await import('../ludusMCP/sshTunnelManager.js');
      
      const tunnelConfig = {
        host: config.sshHost,
        port: 22,
        username: config.sshUser,
        authMethod: config.sshAuthMethod,
        regularPort: 8080,
        primaryPort: 8081,
        privateKeyPath: config.sshAuthMethod === 'key' ? config.sshKeyPath : undefined,
        privateKeyPassphrase: config.sshAuthMethod === 'key' ? config.sshKeyPassphrase : undefined,
        password: config.sshAuthMethod === 'password' ? config.sshPassword : undefined
      };

      console.error(`Attempting SSH tunnel connection to ${config.sshHost}:22 as ${config.sshUser} using ${config.sshAuthMethod} auth...`);
      
      // Create a logger for the tunnel manager
      const logger = new Logger('SSH-Setup');

      const tunnelManager = new LudusSSHTunnelManager(tunnelConfig, logger);
      
      try {
        await tunnelManager.connect();
        console.error('SSH tunnels established successfully using tunnel manager');
        
        // Test tunnel connectivity
        await new Promise(resolve => setTimeout(resolve, 2000));
        const tunnelWorks = await this.testTunnelConnectivity();
        
        if (tunnelWorks) {
          console.error('SSH tunnel connectivity test successful');
          return true;
        } else {
          console.error('SSH tunnels created but connectivity test failed');
          await tunnelManager.disconnect();
          return false;
        }
      } catch (tunnelError: any) {
        console.error(`SSH tunnel creation failed: ${tunnelError.message}`);
        try {
          await tunnelManager.disconnect();
        } catch (disconnectError) {
          // Ignore disconnect errors
        }
        return false;
      }
    } catch (error: any) {
      console.error(`SSH tunnel setup error: ${error.message}`);
      return false;
    }
  }

  private async testTunnelConnectivity(): Promise<boolean> {
    try {
      // Use native Node.js TCP socket testing instead of external curl
      console.error('Testing tunnel connectivity to localhost:8080...');
      
      const isPortOpen = await new Promise<boolean>((resolve) => {
        const socket = new net.Socket();
        
        const timeout = setTimeout(() => {
          socket.destroy();
          resolve(false);
        }, 5000); // 5 second timeout
        
        socket.once('connect', () => {
          clearTimeout(timeout);
          socket.end();
          resolve(true);
        });
        
        socket.once('error', () => {
          clearTimeout(timeout);
          resolve(false);
        });
        
        socket.connect(8080, '127.0.0.1');
      });

      if (isPortOpen) {
        console.error('Tunnel connectivity test successful - port 8080 is accessible');
        return true;
      } else {
        console.error('Tunnel connectivity test failed - port 8080 is not accessible');
        return false;
      }
    } catch (error: any) {
      console.error(`Tunnel connectivity test error: ${error.message}`);
      return false;
    }
  }

  private getConfigFromEnvironment(): LudusConfig | null {
    const requiredVars = {
      adminUser: 'LUDUS_ADMIN_USER',
      wireguardConfig: 'LUDUS_WIREGUARD_CONFIG',
      apiKey: 'LUDUS_API_KEY',
      sshHost: 'LUDUS_SSH_HOST',
      sshUser: 'LUDUS_SSH_USER',
      sshPassword: 'LUDUS_SSH_PASSWORD'
    };

    const config: any = {};
    
    for (const [key, envVar] of Object.entries(requiredVars)) {
      const value = process.env[envVar];
      if (!value) {
        return null; // Missing required environment variable
      }
      config[key] = value;
    }

    // Optional environment variables
    config.ludusUrl = process.env.LUDUS_URL || 'https://198.51.100.1:8080';
    config.verifySSL = Boolean(process.env.LUDUS_VERIFY?.toLowerCase() === 'true');

    return config as LudusConfig;
  }

  /**
   * Try to retrieve credentials from keyring
   */
  private async getConfigFromKeyring(): Promise<LudusConfig | null> {
    try {
      if (!isKeyringSupportAvailable()) {
        console.error(' Keyring support not available on this system');
        return null;
      }

      const credentials = await getCredentials([
        CREDENTIAL_KEYS.ADMIN_USER,
        CREDENTIAL_KEYS.CONNECTION_METHOD,
        CREDENTIAL_KEYS.WIREGUARD_CONFIG_PATH,
        CREDENTIAL_KEYS.API_KEY,
        CREDENTIAL_KEYS.SSH_HOST,
        CREDENTIAL_KEYS.SSH_USER,
              CREDENTIAL_KEYS.SSH_AUTH_METHOD,
      CREDENTIAL_KEYS.SSH_PASSWORD,
      CREDENTIAL_KEYS.SSH_KEY_PATH,
      CREDENTIAL_KEYS.SSH_KEY_PASSPHRASE
      ]);

      const connectionMethod = credentials[CREDENTIAL_KEYS.CONNECTION_METHOD] as 'wireguard' | 'ssh-tunnel' || 'wireguard';
      const sshAuthMethod = credentials[CREDENTIAL_KEYS.SSH_AUTH_METHOD] as 'password' | 'key' || 'password';

      // Check if all required credentials are present
      const baseRequiredCredentials = [
        credentials[CREDENTIAL_KEYS.ADMIN_USER],
        credentials[CREDENTIAL_KEYS.CONNECTION_METHOD],
        credentials[CREDENTIAL_KEYS.API_KEY],
        credentials[CREDENTIAL_KEYS.SSH_HOST],
        credentials[CREDENTIAL_KEYS.SSH_USER],
        credentials[CREDENTIAL_KEYS.SSH_AUTH_METHOD]
      ];

      const hasBaseCredentials = baseRequiredCredentials.every(cred => !!cred);
      const hasWireguardConfig = connectionMethod === 'ssh-tunnel' || !!credentials[CREDENTIAL_KEYS.WIREGUARD_CONFIG_PATH];
      const hasSshAuth = (sshAuthMethod === 'password' && !!credentials[CREDENTIAL_KEYS.SSH_PASSWORD]) ||
                         (sshAuthMethod !== 'password' && !!credentials[CREDENTIAL_KEYS.SSH_KEY_PATH]);

      const hasAllCredentials = hasBaseCredentials && hasWireguardConfig && hasSshAuth;

      if (!hasAllCredentials) {
        return null;
      }

      const baseUrl = connectionMethod === 'ssh-tunnel' ? 'https://localhost:8080' : 'https://198.51.100.1:8080';

      return {
              adminUser: credentials[CREDENTIAL_KEYS.ADMIN_USER]!,
      connectionMethod,
      wireguardConfig: credentials[CREDENTIAL_KEYS.WIREGUARD_CONFIG_PATH] || undefined,
      apiKey: credentials[CREDENTIAL_KEYS.API_KEY]!,
      sshHost: credentials[CREDENTIAL_KEYS.SSH_HOST]!,
      sshUser: credentials[CREDENTIAL_KEYS.SSH_USER]!,
      sshAuthMethod,
      sshPassword: credentials[CREDENTIAL_KEYS.SSH_PASSWORD] || undefined,
      sshKeyPath: credentials[CREDENTIAL_KEYS.SSH_KEY_PATH] || undefined,
      sshKeyPassphrase: credentials[CREDENTIAL_KEYS.SSH_KEY_PASSPHRASE] || undefined,
        ludusUrl: process.env.LUDUS_URL || baseUrl,
        verifySSL: process.env.LUDUS_VERIFY?.toLowerCase() === 'true'
      };
    } catch (error: any) {
      console.error(` Failed to retrieve credentials from keyring: ${error.message}`);
      return null;
    }
  }

  /**
   * Store credentials in keyring after successful validation
   */
  private async storeConfigInKeyring(config: LudusConfig): Promise<void> {
    try {
      if (!isKeyringSupportAvailable()) {
        console.error(' Keyring support not available - credentials will not be stored');
        return;
      }

      const credentialsToStore: Record<string, string> = {
        [CREDENTIAL_KEYS.ADMIN_USER]: config.adminUser,
        [CREDENTIAL_KEYS.CONNECTION_METHOD]: config.connectionMethod,
        [CREDENTIAL_KEYS.API_KEY]: config.apiKey,
        [CREDENTIAL_KEYS.SSH_HOST]: config.sshHost,
        [CREDENTIAL_KEYS.SSH_USER]: config.sshUser,
        [CREDENTIAL_KEYS.SSH_AUTH_METHOD]: config.sshAuthMethod
      };

      // Only store optional configs if they exist
      if (config.wireguardConfig) {
        credentialsToStore[CREDENTIAL_KEYS.WIREGUARD_CONFIG_PATH] = config.wireguardConfig;
      }
      if (config.sshPassword) {
        credentialsToStore[CREDENTIAL_KEYS.SSH_PASSWORD] = config.sshPassword;
      }
      if (config.sshKeyPath) {
        credentialsToStore[CREDENTIAL_KEYS.SSH_KEY_PATH] = config.sshKeyPath;
      }
      if (config.sshKeyPassphrase) {
        credentialsToStore[CREDENTIAL_KEYS.SSH_KEY_PASSPHRASE] = config.sshKeyPassphrase;
      }

      await storeCredentials(credentialsToStore);
      console.error('Credentials stored securely in keyring');
    } catch (error: any) {
      console.error(` Failed to store credentials in keyring: ${error.message}`);
    }
  }

  private async promptForCredentials(): Promise<LudusConfig> {
    console.error('\nLudus MCP Server Initialization');
    console.error('=================================');
    console.error('Please provide the following information (provided by your administrator):\n');

    // Ask for connection method first
    console.error('📡 Connection Method');
    console.error('Choose how to connect to the Ludus API:');
    console.error('  (w) WireGuard VPN - Direct access via WireGuard tunnel');
    console.error('  (s) SSH Tunnel - Access via SSH port forwarding');
    const methodChoice = await this.prompt('Connection method? (w/s) [default: w]: ');
    const connectionMethod: 'wireguard' | 'ssh-tunnel' = methodChoice.toLowerCase() === 's' ? 'ssh-tunnel' : 'wireguard';

    const adminUser = await this.prompt('Ludus Admin Username: ');
    
    let wireguardConfig: string | undefined;
    let ludusUrl: string;
    
    if (connectionMethod === 'wireguard') {
      wireguardConfig = await this.prompt('WireGuard Config Path: ');
      ludusUrl = 'https://198.51.100.1:8080';
    } else {
      console.error('Using SSH tunnel mode - will connect to https://localhost:8080');
      ludusUrl = 'https://localhost:8080';
    }
    
    const apiKey = await this.securePrompt('API Key: ');
    const sshHost = await this.prompt('Ludus Server SSH Host: ');
    const sshUser = await this.prompt('Ludus Server SSH User: ');
    
    // Ask for SSH authentication method
    console.error('\nSSH Authentication Method');
    console.error('Choose SSH authentication method:');
    console.error('  (p) Password - Use SSH password authentication');  
    console.error('  (k) Key - Use SSH key-based authentication');
    
    const authChoice = await this.prompt('SSH auth method? (p/k) [default: p]: ');
    let sshAuthMethod: 'password' | 'key';
    let sshPassword: string | undefined;
    let sshKeyPath: string | undefined;
    let sshKeyPassphrase: string | undefined;
    
    if (authChoice.toLowerCase() === 'k') {
      sshAuthMethod = 'key';
      sshKeyPath = await this.prompt('SSH Key Path: ');
      
      // Ask for passphrase if key is protected
      const hasPassphrase = await this.prompt('Does your SSH key have a passphrase? (y/n) [default: n]: ');
      if (hasPassphrase.toLowerCase() === 'y') {
        sshKeyPassphrase = await this.securePrompt('SSH Key Passphrase: ');
      }
    } else {
      sshAuthMethod = 'password';
      sshPassword = await this.securePrompt('SSH Password: ');
    }

    const useCustomUrl = await this.prompt('Use custom Ludus URL? (y/n) [default: n]: ');
    if (useCustomUrl.toLowerCase() === 'y') {
      ludusUrl = await this.prompt('Ludus URL: ');
    }

    const verifySSL = await this.prompt('Verify SSL certificates? (y/n) [default: n]: ');

    return {
      adminUser,
      connectionMethod,
      wireguardConfig,
      apiKey,
      sshHost,
      sshUser,
      sshAuthMethod,
      sshPassword,
      sshKeyPath,
      sshKeyPassphrase,
      ludusUrl,
      verifySSL: verifySSL.toLowerCase() === 'y'
    };
  }

  /**
   * Main interactive setup flow
   */
  async runSetup(forceInteractive: boolean = false): Promise<SetupResult> {
    try {
      let config: LudusConfig;
      
      // Try to get config from different sources in order of preference
      const envConfig = this.getConfigFromEnvironment();
      const keyringSummary = await getCredentialSummary();
      const keyringSupportAvailable = isKeyringSupportAvailable();
      
      if (forceInteractive) {
        // Force interactive mode - skip environment and keyring checks
        if (process.stdin.isTTY) {
          config = await this.promptForCredentials();
        } else {
          return {
            success: false,
            message: 'Interactive setup requested but no TTY available.'
          };
        }
      } else if (envConfig) {
        console.error('\nUsing configuration from environment variables');
        config = envConfig;
      } else {
        const keyringConfig = await this.getConfigFromKeyring();
        if (keyringConfig) {
          console.error('\nUsing stored credentials from keyring');
          config = keyringConfig;
        } else if (process.stdin.isTTY) {
          // Show keyring status for debugging
          if (keyringSupportAvailable) {
            console.error('\nKeyring credentials summary:');
            for (const [key, exists] of Object.entries(keyringSummary)) {
              console.error(`  ${key}: ${exists ? '' : ''}`);
            }
          }
          
          // Interactive mode
          config = await this.promptForCredentials();
        } else {
          // No TTY and no stored credentials - error
          return {
            success: false,
            message: 'No configuration available. Please set environment variables, run setup interactively, or use --setup-keyring flag.'
          };
        }
      }

      console.error('\nValidating configuration...');

      // Handle connection method
      if (config.connectionMethod === 'wireguard') {
        // 1. Check WireGuard availability
        if (!this.checkWireGuardAvailable()) {
          return {
            success: false,
            message: 'WireGuard is not installed or not available. Please install WireGuard first.'
          };
        }

        // 2. Connect to WireGuard VPN
        console.error('Connecting to WireGuard VPN...');
        if (!config.wireguardConfig || !await this.connectWireGuard(config.wireguardConfig)) {
          return {
            success: false,
            message: 'Failed to connect to WireGuard VPN. Please check your configuration file.'
          };
        }
        console.error('WireGuard VPN connected');
        
        // Important WireGuard usage guidance
        console.error('');
        console.error('IMPORTANT: WireGuard Usage Notes');
        console.error('═══════════════════════════════════════');
        console.error('• WireGuard tunnels must be manually started before launching Claude Desktop');
        console.error('• If WireGuard is down, the MCP client will attempt SSH tunnel fallback');
        console.error('• For automatic startup, consider configuring WireGuard as a Windows service');
        console.error('• To make WireGuard start automatically on boot:');
        console.error('  - Use WireGuard GUI: Right-click tunnel → "Install as Service"');
        console.error('  - Or manually: Run as Admin and use /installtunnelservice flag');
        console.error('');
      } else {
        // SSH tunnel mode
        console.error('Setting up SSH tunnel...');
        if (!await this.createSshTunnel(config)) {
          return {
            success: false,
            message: 'Failed to create SSH tunnel. Please check your SSH credentials.'
          };
        }
        console.error('SSH tunnel established');
      }

      // 3. Validate API key
      console.error('🔑 Validating API key...');
      if (!await this.validateApiKey(config.apiKey, config.ludusUrl)) {
        return {
          success: false,
          message: 'API key validation failed. Please check your API key and server connectivity.'
        };
      }
      console.error('API key validated');

      // 4. Test SSH connectivity
      console.error('🔌 Testing SSH connectivity...');
      if (!await this.testSshConnectivity(config)) {
        return {
          success: false,
          message: 'SSH connectivity test failed. Please check your SSH configuration.'
        };
      }
      console.error('SSH connectivity verified');

      // 5. Store credentials in keyring if setup was successful and credentials were entered interactively
      if (process.stdin.isTTY && !envConfig) {
        await this.storeConfigInKeyring(config);
      }

      // Initialization completed - avoid console output that might interfere with MCP protocol

      // Final success message with WireGuard reminder
      if (config.connectionMethod === 'wireguard') {
        console.error('Setup complete!');
        console.error('');
        console.error('REMEMBER: For Claude Desktop usage:');
        console.error('   1. Manually start your WireGuard tunnel before launching Claude Desktop');
        console.error('   2. Or configure WireGuard as a Windows service for automatic startup');
        console.error('   3. If WireGuard is down, the MCP client will try SSH tunnel fallback');
        console.error('');
      } else {
        console.error('Setup complete!');
      }

      return {
        success: true,
        message: 'Ludus MCP server initialized successfully',
        config
      };
    } catch (error: any) {
      this.logger.error('Initialization failed', { error });
      return {
        success: false,
        message: `Initialization failed: ${error.message}`
      };
    } finally {
      this.rl.close();
    }
  }

  /**
   * Check if setup is complete by verifying stored credentials
   */
  static async checkSetupComplete(): Promise<boolean> {
    try {
      // Check environment variables first
      const envVars = ['LUDUS_ADMIN_USER', 'LUDUS_WIREGUARD_CONFIG', 'LUDUS_API_KEY', 
                      'LUDUS_SSH_HOST', 'LUDUS_SSH_USER', 'LUDUS_SSH_PASSWORD'];
      
      if (envVars.every(v => process.env[v])) {
        return true;
      }

      // Check keyring if available
      if (isKeyringSupportAvailable()) {
        const summary = await getCredentialSummary();
        return Object.values(summary).every(exists => exists);
      }

      return false;
    } catch (error) {
      return false;
    }
  }
} 