#!/usr/bin/env node
// Unified Device Detection Module - iOS & Android
// Auto-detects both USB-connected and wireless devices for both platforms

const { spawn } = require('child_process');
const fs = require('fs').promises;
const path = require('path');

// Config file location - works for both dev and npm package
let DEVICE_CONFIG = path.join(__dirname, 'devices.conf');
// Check if we're in npm package structure (lib/ folder)
if (!require('fs').existsSync(DEVICE_CONFIG)) {
  DEVICE_CONFIG = path.join(__dirname, '../config/devices.conf');
}

// Import Android detection module
let androidDetection;
try {
  androidDetection = require('./androidDeviceDetection');
} catch (err) {
  console.warn('Android detection module not available');
  androidDetection = null;
}

// Detect iOS USB devices using idevice_id
async function detectIOSUSBDevices() {
  return new Promise((resolve) => {
    const udids = [];
    const idevice = spawn('idevice_id', ['-l']);
    
    let output = '';
    idevice.stdout.on('data', (data) => {
      output += data.toString();
    });
    
    idevice.on('close', (code) => {
      if (code === 0 && output.trim()) {
        const devices = output.trim().split('\n').filter(Boolean);
        devices.forEach(udid => {
          udids.push({
            name: `iOS-${udid.substring(0, 8)}`,
            udid: udid.trim(),
            platform: 'ios',
            type: 'usb',
            connectionType: 'usb',
            status: 'unknown' // Will be checked for WDA later
          });
        });
      }
      resolve(udids);
    });
    
    idevice.on('error', () => {
      resolve([]); // idevice_id not installed
    });
  });
}

// Detect USB devices (iOS + Android)
async function detectUSBDevices() {
  const iosDevices = await detectIOSUSBDevices();
  
  let androidDevices = [];
  if (androidDetection) {
    try {
      androidDevices = await androidDetection.detectUSBDevices();
    } catch (err) {
      console.error('Error detecting Android USB devices:', err.message);
    }
  }
  
  return [...iosDevices, ...androidDevices];
}

// Get device info using ideviceinfo
async function getUSBDeviceInfo(udid) {
  return new Promise((resolve) => {
    const idevice = spawn('ideviceinfo', ['-u', udid]);
    
    let output = '';
    idevice.stdout.on('data', (data) => {
      output += data.toString();
    });
    
    idevice.on('close', (code) => {
      if (code === 0 && output.trim()) {
        const info = {};
        const lines = output.split('\n');
        
        lines.forEach(line => {
          if (line.includes('DeviceName:')) {
            info.name = line.split(':')[1].trim();
          }
          if (line.includes('ProductVersion:')) {
            info.osVersion = line.split(':')[1].trim();
          }
        });
        
        resolve(info);
      } else {
        resolve(null);
      }
    });
    
    idevice.on('error', () => {
      resolve(null);
    });
  });
}

// Load all devices from config (iOS + Android, USB and wireless)
async function loadDevicesFromConfig() {
  try {
    const content = await fs.readFile(DEVICE_CONFIG, 'utf-8');
    const devices = content
      .split('\n')
      .filter(line => line.trim() && !line.startsWith('#'))
      .map(line => {
        const parts = line.split(',').map(s => s.trim());
        const [name, udid, ip, platform, type] = parts;
        
        // Auto-detect platform if not specified
        let devicePlatform = platform || 'ios'; // Default for backward compatibility
        
        // Smart platform detection based on UDID format
        if (!platform) {
          // Android wireless: IP:PORT format (e.g., 192.168.1.100:5555)
          if (udid && udid.includes(':') && udid.match(/^\d+\.\d+\.\d+\.\d+:\d+$/)) {
            devicePlatform = 'android';
          }
          // Android USB: Short serial (not UUID format)
          else if (udid && udid.length < 20 && !udid.includes('-')) {
            devicePlatform = 'android';
          }
          // iOS: Long UUID with dashes
          else if (udid && udid.includes('-') && udid.length > 30) {
            devicePlatform = 'ios';
          }
        }
        
        const connectionType = type || (ip ? 'wireless' : 'usb');
        
        return { 
          name, 
          udid, 
          ip: ip || '', 
          platform: devicePlatform,
          type: connectionType, 
          connectionType,
          status: 'unknown' 
        };
      });
    return devices;
  } catch (error) {
    return [];
  }
}

// Load wireless devices from config (backwards compatibility)
async function loadWirelessDevices() {
  const devices = await loadDevicesFromConfig();
  return devices.filter(d => d.ip);
}

// Save USB device to config if not already present
async function saveUSBDeviceToConfig(device) {
  try {
    const existingDevices = await loadDevicesFromConfig();
    const exists = existingDevices.some(d => d.udid === device.udid);
    
    if (!exists) {
      // Read current config
      let content = '';
      try {
        content = await fs.readFile(DEVICE_CONFIG, 'utf-8');
      } catch (error) {
        // Config doesn't exist, create with header
        content = `# Device Configuration (Auto-updated)
# Format: device_name,udid,ip_address,platform,type
# Platform: ios | android
# Type: usb | wireless
# 
# 🔌 USB DEVICES: Automatically detected and saved here
#    - No configuration needed for USB connection
#    - Add IP address to enable wireless support later
#
# 📡 WIRELESS DEVICES: Manually add with IP address
#    - Format: device_name,udid,ip_address,platform,wireless
#    - iOS: Device must be paired in Xcode, WebDriverAgent running
#    - Android: Enable wireless ADB first
#
# Example entries:
# iPhone17,00008130-001945C63ED3401E,,ios,usb           (iOS USB - auto-detected)
# iPhone16P,00008140-001C24361E41801C,10.173.221.204,ios,wireless  (iOS Wireless)
# Pixel8,1A2B3C4D5E6F,,android,usb                      (Android USB - auto-detected)
# GalaxyS23,ABCD1234,192.168.1.150,android,wireless     (Android Wireless)

`;
      }
      
      // Append new device with platform info
      const platform = device.platform || 'ios';
      const newEntry = `${device.name},${device.udid},,${platform},usb\n`;
      content += newEntry;
      
      await fs.writeFile(DEVICE_CONFIG, content, 'utf-8');
      console.log(`✅ Auto-saved ${platform.toUpperCase()} USB device to config: ${device.name}`);
      return true;
    }
    return false;
  } catch (error) {
    console.error('Failed to save USB device to config:', error);
    return false;
  }
}

// Check wireless device connectivity
function checkWirelessConnectivity(device) {
  return new Promise((resolve) => {
    const curl = spawn('curl', [
      '-s',
      '--connect-timeout', '2',
      '--max-time', '3',
      `http://${device.ip}:8100/status`
    ]);
    
    let output = '';
    curl.stdout.on('data', (data) => {
      output += data.toString();
    });
    
    curl.on('close', () => {
      resolve(output.includes('"state"'));
    });
    
    setTimeout(() => {
      curl.kill();
      resolve(false);
    }, 3000);
  });
}

// Check USB device WDA connectivity on specific port
function checkUSBWDAConnectivityOnPort(port) {
  return new Promise((resolve) => {
    const curl = spawn('curl', [
      '-s',
      '--connect-timeout', '1',
      '--max-time', '2',
      `http://localhost:${port}/status`
    ]);
    
    let output = '';
    curl.stdout.on('data', (data) => {
      output += data.toString();
    });
    
    curl.on('close', () => {
      resolve(output.includes('"state"'));
    });
    
    setTimeout(() => {
      curl.kill();
      resolve(false);
    }, 2500);
  });
}

// Discover all devices (iOS + Android, USB + Wireless)
async function discoverAllDevices() {
  // Get USB devices (iOS + Android)
  const usbDevices = await detectUSBDevices();
  
  // Enhance USB devices with names and check connectivity
  const WDA_PORT_BASE = 8100;
  for (let i = 0; i < usbDevices.length; i++) {
    const device = usbDevices[i];
    
    if (device.platform === 'ios') {
      // Get iOS device name and OS version
      const info = await getUSBDeviceInfo(device.udid);
      if (info) {
        if (info.name) device.name = info.name;
        if (info.osVersion) device.osVersion = info.osVersion;
      }
      device.connectionType = 'usb';
      
      // Check WDA connectivity
      const port = WDA_PORT_BASE + i;
      const wdaRunning = await checkUSBWDAConnectivityOnPort(port);
      device.status = wdaRunning ? 'online' : 'offline';
      device.port = port;
    } else if (device.platform === 'android') {
      // Android status already set by androidDetection module
      device.status = device.status || 'online'; // Assume online if connected
    }
    
    // Auto-save to config
    await saveUSBDeviceToConfig(device);
  }
  
  // Get wireless devices (iOS + Android)
  const wirelessDevices = await loadWirelessDevices();
  
  // Check wireless connectivity
  const wirelessChecks = wirelessDevices.map(async (device) => {
    try {
      let isOnline = false;
      
      if (device.platform === 'ios') {
        isOnline = await checkWirelessConnectivity(device);
      } else if (device.platform === 'android' && androidDetection) {
        // For Android wireless, check if device is in adb devices list
        try {
          const wirelessDevices = await androidDetection.detectWirelessDevices();
          isOnline = wirelessDevices.some(d => d.udid === device.udid || d.serial === device.udid);
        } catch (err) {
          isOnline = false;
        }
      }
      
      return { ...device, connectionType: 'wireless', status: isOnline ? 'online' : 'offline' };
    } catch (error) {
      return { ...device, connectionType: 'wireless', status: 'error' };
    }
  });
  
  const wirelessResults = await Promise.all(wirelessChecks);
  
  // Combine and deduplicate by UDID
  const allDevices = [...usbDevices];
  const usbUdids = new Set(usbDevices.map(d => d.udid));
  
  wirelessResults.forEach(device => {
    if (!usbUdids.has(device.udid)) {
      allDevices.push(device);
    }
  });
  
  return allDevices;
}

// CLI Mode
if (require.main === module) {
  (async () => {
    console.log('🔍 Discovering iOS & Android devices...\n');
    
    const devices = await discoverAllDevices();
    
    if (devices.length === 0) {
      console.log('❌ No devices found\n');
      console.log('Make sure:');
      console.log('  iOS:');
      console.log('    - USB devices are connected and trusted');
      console.log('    - Wireless devices are configured in devices.conf');
      console.log('    - libimobiledevice is installed: brew install libimobiledevice');
      console.log('  Android:');
      console.log('    - USB debugging is enabled');
      console.log('    - Device is authorized (check device screen)');
      console.log('    - ADB is installed: brew install android-platform-tools\n');
      process.exit(1);
    }
    
    console.log(`Found ${devices.length} device(s):\n`);
    devices.forEach((device, idx) => {
      const platform = device.platform || 'ios';
      const type = device.type || device.connectionType || 'usb';
      const platformIcon = platform === 'ios' ? '🍎' : '🤖';
      const typeIcon = type === 'usb' ? '🔌' : '📡';
      const status = device.status === 'online' ? '✅' : device.status === 'connected' ? '✅' : '⚠️';
      
      console.log(`${idx + 1}. ${platformIcon} ${typeIcon} ${device.name} (${platform.toUpperCase()} - ${type.toUpperCase()}) ${status}`);
      console.log(`   UDID: ${device.udid || device.serial}`);
      if (device.ip) console.log(`   IP: ${device.ip}`);
      if (device.androidVersion) console.log(`   Android: ${device.androidVersion}`);
      console.log('');
    });
    
    // Output JSON for scripting
    if (process.argv.includes('--json')) {
      console.log(JSON.stringify(devices, null, 2));
    }
  })();
}

module.exports = {
  detectUSBDevices,
  getUSBDeviceInfo,
  loadDevicesFromConfig,
  loadWirelessDevices,
  checkWirelessConnectivity,
  checkUSBWDAConnectivityOnPort,
  saveUSBDeviceToConfig,
  discoverAllDevices
};
