import { db } from '../database/db';
import { NetworkDriverFactory } from '../modules/network/driver.factory';
import { WalletService } from '../modules/billing/wallet.service';
import { BillingService } from '../modules/billing/billing.service';
import { DisconnectionWorker } from '../modules/workers/disconnection.worker';
import { OltService } from '../modules/olt/olt.service';
import { PaymentGatewayService } from '../modules/payments/payment.service';
import { SnmpScraperEngine } from '../modules/olt/snmp-scraper';

let passed = 0;
let failed = 0;

function assert(condition: boolean, testName: string) {
  if (condition) {
    console.log(`  ✅ PASS: ${testName}`);
    passed++;
  } else {
    console.error(`  ❌ FAIL: ${testName}`);
    failed++;
  }
}

async function runTests() {
  console.log(`\n======================================================`);
  console.log(`🧪 RUNNING NEXT-GEN ISP BILLING TEST SUITE`);
  console.log(`======================================================\n`);

  // 1. Unified Network Driver Tests
  console.log(`[1] Testing Unified Network Driver Integration (MikroTik & FreeRADIUS)...`);
  const mikrotikRes = await NetworkDriverFactory.executeAction('createUser', {
    id: 'sub_test_mt',
    username: 'test.mt.user',
    driver_type: 'MIKROTIK_API',
    speed_mbps: 50,
    mikrotik_profile: 'prof_50mbps',
    status: 'active'
  });
  assert(mikrotikRes.success && mikrotikRes.driver === 'MIKROTIK_API', 'MikroTik createUser executed');

  const radiusRes = await NetworkDriverFactory.executeAction('createUser', {
    id: 'sub_test_rad',
    username: 'test.rad.user',
    driver_type: 'RADIUS',
    speed_mbps: 20,
    radius_group: 'group_20mbps',
    status: 'active'
  });
  assert(radiusRes.success && radiusRes.driver === 'RADIUS', 'FreeRADIUS createUser synced radcheck/radreply');

  const radiusSuspend = await NetworkDriverFactory.executeAction('suspendUser', {
    id: 'sub_test_rad',
    username: 'test.rad.user',
    driver_type: 'RADIUS',
    status: 'expired'
  });
  assert(radiusSuspend.success && radiusSuspend.details?.radreplyPool === 'expired-walled-garden', 'FreeRADIUS suspendUser switched to walled garden pool and generated CoA');

  // 2. Concurrency & Row-Level Locking Test on Reseller Pre-Paid Wallet
  console.log(`\n[2] Testing Row-Level Locking & Pre-Paid Wallet Concurrency...`);
  const initialSummary = WalletService.getWalletSummary('reseller_uttara');
  const initialBalance = initialSummary.wallet.balance;

  // Run 5 simultaneous wholesale deductions of 400 BDT
  const deductionPromises = Array.from({ length: 5 }).map((_, i) =>
    WalletService.deductWholesale('reseller_uttara', 400.0, `concurrent_sub_${i}`, 'Starter Fiber 20 Mbps')
  );

  const deductionResults = await Promise.all(deductionPromises);
  const allSuccessful = deductionResults.every(r => r.success);
  const finalSummary = WalletService.getWalletSummary('reseller_uttara');
  const expectedBalance = initialBalance - (5 * 400.0);

  assert(allSuccessful, 'All 5 concurrent wholesale deductions succeeded without race condition');
  assert(finalSummary.wallet.balance === expectedBalance, `Reseller wallet balance correctly deducted (${initialBalance} -> ${finalSummary.wallet.balance})`);

  // 3. Asynchronous Automated Disconnection Engine Test
  console.log(`\n[3] Testing Asynchronous Automated Disconnection Engine...`);
  // Seed an expired subscriber
  const testExpiredSub = {
    id: 'sub_exp_test',
    tenant_id: 'tenant_main',
    username: 'auto.expired.user',
    password_hash: 'pass123',
    full_name: 'Auto Expired User',
    phone: '01700000099',
    driver_type: 'MIKROTIK_API' as const,
    package_id: 'pkg_starter_20m',
    connection_type: 'PPPOE' as const,
    fup_used_bytes: 0,
    status: 'active' as const,
    expiration_date: new Date(Date.now() - 1000 * 60 * 10).toISOString(), // 10 mins ago
    created_at: new Date().toISOString(),
    updated_at: new Date().toISOString()
  };
  db.subscribers.push(testExpiredSub);

  const report = await DisconnectionWorker.executeScan();
  const disconnected = report.disconnectedSubscribers.some(d => d.username === 'auto.expired.user');
  const subInDb = db.subscribers.find(s => s.username === 'auto.expired.user');
  assert(disconnected && subInDb?.status === 'expired', 'Disconnection worker detected expired subscriber and dropped to walled-garden');

  // 4. OLT Laser Scraper & Color Threshold Calculations
  console.log(`\n[4] Testing OLT Laser Diagnostic Scraper & Health Boundaries...`);
  const healthyCheck = SnmpScraperEngine.calculateLaserHealth(-18.5);
  assert(healthyCheck.colorCode === 'GREEN' && healthyCheck.status === 'healthy', 'Green status for -18.5 dBm (-8 to -24 dBm)');

  const warningCheck = SnmpScraperEngine.calculateLaserHealth(-25.5);
  assert(warningCheck.colorCode === 'YELLOW' && warningCheck.status === 'warning', 'Yellow warning for -25.5 dBm (-24.1 to -27 dBm)');

  const criticalCheck = SnmpScraperEngine.calculateLaserHealth(-29.2);
  assert(criticalCheck.colorCode === 'RED' && criticalCheck.status === 'critical_fault', 'Red critical fault for -29.2 dBm (> -27.1 dBm)');

  const laserResults = await OltService.runLaserDiagnosticsScrape();
  assert(laserResults.length > 0, `Laser diagnostics polled ${laserResults.length} ONUs`);
  const criticalOnu = laserResults.find(r => r.status === 'critical_fault');
  assert(criticalOnu?.telegramAlertPushed === true, 'Critical fault automatically triggered Telegram alert');

  // 5. bKash Pay Bill & SIM Webhook Integration
  console.log(`\n[5] Testing bKash Pay Bill & SIM SMS Automation Webhooks...`);
  const validateRes = PaymentGatewayService.validatePayBillCustomer('tanvir.ahmed');
  assert(validateRes.success && validateRes.data?.customerId === 'tanvir.ahmed', 'bKash /api/bkash/validate returns valid customer and bill');

  const invalidValidateRes = PaymentGatewayService.validatePayBillCustomer('non_existent_user');
  assert(!invalidValidateRes.success && invalidValidateRes.errorCode === 'CUSTOMER_NOT_FOUND', 'bKash validate returns CUSTOMER_NOT_FOUND for invalid accounts');

  const payBillConfirm = await PaymentGatewayService.confirmPayBillPayment({
    trxId: `BK_CONFIRM_${Date.now()}`,
    customerId: 'rahim.khan',
    amount: 650.00
  });
  assert(payBillConfirm.success && payBillConfirm.subscriber.status === 'active', 'bKash Pay Bill /confirm renewed subscriber and unblocked network profile');

  // Test SIM SMS Regex parser
  const dynamicTrx = `BK9SIM${Date.now()}`;
  const rawSms = `You have received Tk 600.00 from 01712345678. Ref karim.hassan. Fee Tk 0.00. Balance Tk 18,200.00. TrxID ${dynamicTrx} at 25/08/2026 18:30`;
  const simWebhookRes = await PaymentGatewayService.processSimSmsWebhook({
    rawSmsOrNotification: rawSms
  });
  assert(simWebhookRes.success && simWebhookRes.subscriber.username === 'karim.hassan', 'SIM SMS webhook parsed TrxID, Amount, and Reference correctly');

  console.log(`\n======================================================`);
  console.log(`🏁 TEST RESULTS: ${passed} PASSED, ${failed} FAILED`);
  console.log(`======================================================\n`);

  if (failed > 0) {
    process.exit(1);
  }
}

runTests().catch(err => {
  console.error('Fatal test execution error:', err);
  process.exit(1);
});
