#!/usr/bin/env node

/**
 * Query Omada Controller devices and configuration
 * Uses admin credentials to connect and list hardware
 */

import { OmadaClient, DevicesService, NetworksService, SitesService } from './omada-api/dist/index.js';
import { readFileSync } from 'fs';
import { join } from 'path';
import { homedir } from 'os';

// Load environment variables
const envPath = join(homedir(), '.env');
let envVars = {};

try {
  const envFile = readFileSync(envPath, 'utf8');
  envFile.split('\n').forEach(line => {
    if (line.includes('=') && !line.trim().startsWith('#')) {
      const [key, ...values] = line.split('=');
      if (key && /^[A-Z_][A-Z0-9_]*$/.test(key.trim())) {
        let value = values.join('=').trim();
        if ((value.startsWith('"') && value.endsWith('"')) || 
            (value.startsWith("'") && value.endsWith("'"))) {
          value = value.slice(1, -1);
        }
        envVars[key.trim()] = value;
      }
    }
  });
} catch (error) {
  console.error('Error loading .env file:', error.message);
  process.exit(1);
}

// Get configuration - use admin credentials if available, otherwise fall back to API_KEY/SECRET
const baseUrl = envVars.OMADA_CONTROLLER_URL || 'https://192.168.11.8:8043';
const username = envVars.OMADA_ADMIN_USERNAME || envVars.OMADA_API_KEY;
const password = envVars.OMADA_ADMIN_PASSWORD || envVars.OMADA_API_SECRET;
const siteId = envVars.OMADA_SITE_ID;
const verifySSL = envVars.OMADA_VERIFY_SSL !== 'false';

if (!username || !password) {
  console.error('Error: Missing credentials');
  console.error('Required: OMADA_ADMIN_USERNAME and OMADA_ADMIN_PASSWORD (or OMADA_API_KEY/OMADA_API_SECRET)');
  process.exit(1);
}

console.log('=== Omada Controller Device Query ===\n');
console.log(`Controller URL: ${baseUrl}`);
console.log(`Site ID: ${siteId || 'auto-detect'}`);
console.log(`SSL Verification: ${verifySSL}\n`);

// Create client with admin credentials (using clientId/clientSecret fields for username/password)
const client = new OmadaClient({
  baseUrl,
  clientId: username,
  clientSecret: password,
  siteId,
  verifySSL,
});

async function queryDevices() {
  try {
    console.log('1. Authenticating...');
    const auth = client.getAuth();
    const token = await auth.getAccessToken();
    console.log(`   ✓ Authentication successful\n`);

    console.log('2. Getting site information...');
    const sitesService = new SitesService(client);
    const sites = await sitesService.listSites();
    console.log(`   ✓ Found ${sites.length} site(s)`);
    sites.forEach((site, index) => {
      console.log(`   Site ${index + 1}: ${site.name} (${site.id})`);
      if (site.id === siteId) {
        console.log(`      ^ Using this site`);
      }
    });
    console.log('');

    const effectiveSiteId = siteId || (sites[0]?.id);
    if (!effectiveSiteId) {
      throw new Error('No site ID available');
    }
    console.log(`3. Using site ID: ${effectiveSiteId}\n`);

    console.log('4. Listing all devices...');
    const devicesService = new DevicesService(client);
    const devices = await devicesService.listDevices({ siteId: effectiveSiteId });
    console.log(`   ✓ Found ${devices.length} device(s)\n`);
    
    if (devices.length > 0) {
      console.log('   DEVICE INVENTORY:');
      console.log('   ' + '='.repeat(80));
      
      const routers = devices.filter(d => d.type === 'router' || d.type === 'Gateway');
      const switches = devices.filter(d => d.type === 'switch' || d.type === 'Switch');
      const aps = devices.filter(d => d.type === 'ap' || d.type === 'AccessPoint');
      const others = devices.filter(d => 
        d.type !== 'router' && d.type !== 'Gateway' && 
        d.type !== 'switch' && d.type !== 'Switch' && 
        d.type !== 'ap' && d.type !== 'AccessPoint'
      );

      if (routers.length > 0) {
        console.log(`\n   ROUTERS (${routers.length}):`);
        routers.forEach((device, index) => {
          const status = device.status === 1 ? '🟢 Online' : device.status === 0 ? '🔴 Offline' : '🟡 Unknown';
          console.log(`   ${index + 1}. ${device.name || 'Unnamed'}`);
          console.log(`      Model: ${device.model || 'N/A'}`);
          console.log(`      Status: ${status}`);
          console.log(`      IP: ${device.ip || 'N/A'}`);
          console.log(`      MAC: ${device.mac || 'N/A'}`);
          console.log(`      Device ID: ${device.id || 'N/A'}`);
          console.log(`      Firmware: ${device.firmwareVersion || 'N/A'}`);
          console.log('');
        });
      }

      if (switches.length > 0) {
        console.log(`\n   SWITCHES (${switches.length}):`);
        switches.forEach((device, index) => {
          const status = device.status === 1 ? '🟢 Online' : device.status === 0 ? '🔴 Offline' : '🟡 Unknown';
          console.log(`   ${index + 1}. ${device.name || 'Unnamed'}`);
          console.log(`      Model: ${device.model || 'N/A'}`);
          console.log(`      Status: ${status}`);
          console.log(`      IP: ${device.ip || 'N/A'}`);
          console.log(`      MAC: ${device.mac || 'N/A'}`);
          console.log(`      Device ID: ${device.id || 'N/A'}`);
          console.log(`      Firmware: ${device.firmwareVersion || 'N/A'}`);
          console.log('');
        });
      }

      if (aps.length > 0) {
        console.log(`\n   ACCESS POINTS (${aps.length}):`);
        aps.forEach((device, index) => {
          const status = device.status === 1 ? '🟢 Online' : device.status === 0 ? '🔴 Offline' : '🟡 Unknown';
          console.log(`   ${index + 1}. ${device.name || 'Unnamed'}`);
          console.log(`      Model: ${device.model || 'N/A'}`);
          console.log(`      Status: ${status}`);
          console.log(`      IP: ${device.ip || 'N/A'}`);
          console.log(`      MAC: ${device.mac || 'N/A'}`);
          console.log('');
        });
      }

      if (others.length > 0) {
        console.log(`\n   OTHER DEVICES (${others.length}):`);
        others.forEach((device, index) => {
          const status = device.status === 1 ? '🟢 Online' : device.status === 0 ? '🔴 Offline' : '🟡 Unknown';
          console.log(`   ${index + 1}. ${device.name || 'Unnamed'} (${device.type || 'Unknown'})`);
          console.log(`      Model: ${device.model || 'N/A'}`);
          console.log(`      Status: ${status}`);
          console.log(`      IP: ${device.ip || 'N/A'}`);
          console.log('');
        });
      }
    } else {
      console.log('   No devices found');
    }

    console.log('\n5. Listing VLANs...');
    const networksService = new NetworksService(client);
    const vlans = await networksService.listVLANs({ siteId: effectiveSiteId });
    console.log(`   ✓ Found ${vlans.length} VLAN(s)\n`);
    
    if (vlans.length > 0) {
      console.log('   VLAN CONFIGURATION:');
      console.log('   ' + '='.repeat(80));
      vlans.forEach((vlan, index) => {
        console.log(`\n   ${index + 1}. VLAN ${vlan.vlanId || 'N/A'}: ${vlan.name || 'Unnamed'}`);
        if (vlan.subnet) console.log(`      Subnet: ${vlan.subnet}`);
        if (vlan.gateway) console.log(`      Gateway: ${vlan.gateway}`);
        if (vlan.dhcpEnable !== undefined) {
          console.log(`      DHCP: ${vlan.dhcpEnable ? 'Enabled' : 'Disabled'}`);
          if (vlan.dhcpEnable && vlan.dhcpRangeStart && vlan.dhcpRangeEnd) {
            console.log(`      DHCP Range: ${vlan.dhcpRangeStart} - ${vlan.dhcpRangeEnd}`);
          }
        }
        if (vlan.dns1) console.log(`      DNS1: ${vlan.dns1}`);
        if (vlan.dns2) console.log(`      DNS2: ${vlan.dns2}`);
      });
    } else {
      console.log('   No VLANs configured');
    }

    console.log('\n' + '='.repeat(80));
    console.log('=== Query completed successfully! ===\n');
    
  } catch (error) {
    console.error('\n=== Query failed ===');
    console.error('Error:', error.message);
    if (error.stack) {
      console.error('\nStack trace:');
      console.error(error.stack);
    }
    process.exit(1);
  }
}

queryDevices();

