// ============================================
// SELF TEST FUNCTIONS (shared across pages)
// ============================================

// Cache for operators data
let operatorsDataSelfTest = null;

function loadOperatorsDataSelfTest() {
  return new Promise((resolve, reject) => {
    if (operatorsDataSelfTest) {
      resolve(operatorsDataSelfTest);
      return;
    }
    $.ajax({
      url: 'assets/data/operators.json',
      dataType: 'json',
      method: 'GET',
      success: function(data) {
        operatorsDataSelfTest = data;
        resolve(data);
      },
      error: function(xhr, status, error) {
        console.error('Failed to load operators data:', error);
        reject(error);
      }
    });
  });
}

// Global object to store test results for report
let selfTestReport = {
  timestamp: '',
  deviceId: '',
  modemVersion: '',
  results: {},
  rawResponses: {}
};

function runSelfTest() {
  console.log("Starting Self Test...");

  // Reset report
  selfTestReport = {
    timestamp: new Date().toISOString(),
    deviceId: document.querySelector('.sideBar_sensorName')?.textContent || 'Unknown',
    modemVersion: document.getElementById('modem_version')?.textContent || 'Unknown',
    results: {},
    rawResponses: {}
  };

  // Reset UI
  resetSelfTestUI();

  // Show modal
  const modal = new bootstrap.Modal(document.getElementById('selfTestModal'));
  modal.show();

  // Disable buttons during test
  document.getElementById('selfTestCloseBtn').disabled = true;
  document.getElementById('selfTestDoneBtn').disabled = true;
  document.getElementById('selfTestCopyBtn').disabled = true;
  document.querySelectorAll('.btn_selfTest').forEach(btn => btn.disabled = true);

  // Start test sequence
  selfTestSequence();
}

function resetSelfTestUI() {
  // Reset status
  document.getElementById('selftest_status').innerHTML = `
    <div class="d-flex align-items-center text-muted">
      <div class="spinner-border spinner-border-sm me-2" role="status"></div>
      <span>Preparing test...</span>
    </div>`;

  // Reset test items
  document.getElementById('test_wifi_status').className = 'badge bg-secondary';
  document.getElementById('test_wifi_status').textContent = 'Pending';
  document.getElementById('test_wifi_detail').textContent = 'Waiting...';

  document.getElementById('test_modem_status').className = 'badge bg-secondary';
  document.getElementById('test_modem_status').textContent = 'Pending';
  document.getElementById('test_modem_detail').textContent = 'Waiting...';

  document.getElementById('test_sim_status').className = 'badge bg-secondary';
  document.getElementById('test_sim_status').textContent = 'Pending';
  document.getElementById('test_sim_detail').textContent = 'Waiting...';

  document.getElementById('test_signal_status').className = 'badge bg-secondary';
  document.getElementById('test_signal_status').textContent = 'Pending';
  document.getElementById('test_signal_detail').textContent = 'Waiting...';

  document.getElementById('test_network_status').className = 'badge bg-secondary';
  document.getElementById('test_network_status').textContent = 'Pending';
  document.getElementById('test_network_detail').textContent = 'Waiting...';

  // Reset sensor tests
  document.getElementById('sensor_tests_container').innerHTML = '';
  document.getElementById('comm_tests_separator').style.display = 'none';

  // Reset logs
  document.getElementById('selftest_logs').innerHTML = '';

  // Reset summary
  document.getElementById('selftest_summary').innerHTML = '';
}

function addSelfTestLog(message, isRaw = false) {
  const logsEl = document.getElementById('selftest_logs');
  const timestamp = new Date().toLocaleTimeString();

  if (isRaw) {
    // Raw AT response - format nicely
    logsEl.textContent += `[${timestamp}] >>> RAW RESPONSE:\n${message}\n<<<\n`;
  } else {
    logsEl.textContent += `[${timestamp}] ${message}\n`;
  }

  // Auto-scroll to bottom
  logsEl.parentElement.scrollTop = logsEl.parentElement.scrollHeight;
}

function updateTestStatus(testId, status, detail, badge) {
  document.getElementById(`test_${testId}_status`).className = `badge ${badge}`;
  document.getElementById(`test_${testId}_status`).textContent = status;
  document.getElementById(`test_${testId}_detail`).textContent = detail;

  // Store result in report
  selfTestReport.results[testId] = {
    status: status,
    detail: detail
  };
}

function setConfigMode(enabled) {
  return new Promise((resolve, reject) => {
    addSelfTestLog(`Setting modem_config_mode to ${enabled}...`);

    $.ajax({
      url: `launcher.php?type=update_config_sqlite&param=modem_config_mode&value=${enabled}`,
      dataType: 'json',
      method: 'GET',
      cache: false,
      success: function(response) {
        if (response.success) {
          addSelfTestLog(`modem_config_mode set to ${enabled}`);
          // Update checkbox state if it exists on the page
          const checkbox = document.getElementById('check_modem_configMode');
          if (checkbox) checkbox.checked = enabled;
          resolve(true);
        } else {
          addSelfTestLog(`Failed to set modem_config_mode: ${response.error || 'Unknown error'}`);
          reject(new Error(response.error || 'Failed to set config mode'));
        }
      },
      error: function(xhr, status, error) {
        addSelfTestLog(`AJAX error setting config mode: ${error}`);
        reject(new Error(error));
      }
    });
  });
}

function sendATCommand(command, timeout) {
  return new Promise((resolve, reject) => {
    addSelfTestLog(`Sending AT command: ${command} (timeout: ${timeout}s)`);

    $.ajax({
      url: `launcher.php?type=sara&port=ttyAMA2&command=${encodeURIComponent(command)}&timeout=${timeout}`,
      dataType: 'text',
      method: 'GET',
      success: function(response) {
        // Store raw response in report
        selfTestReport.rawResponses[command] = response;

        // Log raw response
        addSelfTestLog(response.trim(), true);

        resolve(response);
      },
      error: function(xhr, status, error) {
        addSelfTestLog(`AT command error: ${error}`);
        selfTestReport.rawResponses[command] = `ERROR: ${error}`;
        reject(new Error(error));
      }
    });
  });
}

function delaySelfTest(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

async function selfTestSequence() {
  let testsPassed = 0;
  let testsFailed = 0;

  try {
    // Collect system info at the start
    document.getElementById('selftest_status').innerHTML = `
      <div class="d-flex align-items-center text-primary">
        <div class="spinner-border spinner-border-sm me-2" role="status"></div>
        <span>Collecting system information...</span>
      </div>`;

    // Get system info from config
    try {
      const configResponse = await new Promise((resolve, reject) => {
        $.ajax({
          url: 'launcher.php?type=get_config_sqlite',
          dataType: 'json',
          method: 'GET',
          success: function(data) { resolve(data); },
          error: function(xhr, status, error) { reject(new Error(error)); }
        });
      });

      // Store in report
      selfTestReport.deviceId = configResponse.deviceID || 'Unknown';
      selfTestReport.deviceName = configResponse.deviceName || 'Unknown';
      selfTestReport.modemVersion = configResponse.modem_version || 'Unknown';
      selfTestReport.latitude = configResponse.latitude_raw || 'N/A';
      selfTestReport.longitude = configResponse.longitude_raw || 'N/A';
      selfTestReport.config = configResponse;

      // Get RTC time
      try {
        const rtcTime = await new Promise((resolve, reject) => {
          $.ajax({
            url: 'launcher.php?type=RTC_time',
            dataType: 'text',
            method: 'GET',
            success: function(data) { resolve(data.trim()); },
            error: function(xhr, status, error) { resolve('N/A'); }
          });
        });
        selfTestReport.systemTime = rtcTime;
      } catch (e) {
        selfTestReport.systemTime = 'N/A';
      }

      // Log system info
      addSelfTestLog('════════════════════════════════════════════════════════');
      addSelfTestLog('           NEBULEAIR PRO 4G - SELF TEST');
      addSelfTestLog('════════════════════════════════════════════════════════');
      addSelfTestLog(`Device ID: ${selfTestReport.deviceId}`);
      addSelfTestLog(`Device Name: ${selfTestReport.deviceName}`);
      addSelfTestLog(`Modem Version: ${selfTestReport.modemVersion}`);
      addSelfTestLog(`RTC Time: ${selfTestReport.systemTime}`);
      addSelfTestLog(`Browser Time: ${new Date().toLocaleString()}`);
      addSelfTestLog(`GPS: ${selfTestReport.latitude}, ${selfTestReport.longitude}`);
      addSelfTestLog('────────────────────────────────────────────────────────');
      addSelfTestLog('');

    } catch (error) {
      addSelfTestLog(`Warning: Could not get system config: ${error.message}`);
    }

    await delaySelfTest(300);

    // ═══════════════════════════════════════════════════════
    // SENSOR TESTS - Test enabled sensors based on config
    // ═══════════════════════════════════════════════════════
    const config = selfTestReport.config || {};
    const sensorTests = [];

    // NPM is always present
    sensorTests.push({ id: 'npm', name: 'NextPM (Particles)', type: 'npm', port: 'ttyAMA5' });

    // BME280 if enabled
    if (config.BME280) {
      sensorTests.push({ id: 'bme280', name: 'BME280 (Temp/Hum)', type: 'BME280' });
    }

    // Noise if enabled
    if (config.NOISE) {
      sensorTests.push({ id: 'noise', name: 'Noise Sensor', type: 'noise' });
    }

    // Envea if enabled
    if (config.envea) {
      sensorTests.push({ id: 'envea', name: 'Envea (Gas Sensors)', type: 'envea' });
    }

    // RTC module is always present (DS3231)
    sensorTests.push({ id: 'rtc', name: 'RTC Module (DS3231)', type: 'rtc' });

    // Create sensor test UI entries dynamically
    const sensorContainer = document.getElementById('sensor_tests_container');
    sensorContainer.innerHTML = '';

    sensorTests.forEach(sensor => {
      sensorContainer.innerHTML += `
        <div class="list-group-item d-flex justify-content-between align-items-center" id="test_${sensor.id}">
          <div>
            <strong>${sensor.name}</strong>
            <div class="small text-muted" id="test_${sensor.id}_detail">Waiting...</div>
          </div>
          <span id="test_${sensor.id}_status" class="badge bg-secondary">Pending</span>
        </div>`;
    });

    addSelfTestLog('');
    addSelfTestLog('────────────────────────────────────────────────────────');
    addSelfTestLog('SENSOR TESTS');
    addSelfTestLog('────────────────────────────────────────────────────────');

    // Run each sensor test
    for (const sensor of sensorTests) {
      await delaySelfTest(500);

      document.getElementById('selftest_status').innerHTML = `
        <div class="d-flex align-items-center text-primary">
          <div class="spinner-border spinner-border-sm me-2" role="status"></div>
          <span>Testing ${sensor.name}...</span>
        </div>`;

      updateTestStatus(sensor.id, 'Testing...', 'Reading sensor data...', 'bg-info');
      addSelfTestLog(`Testing ${sensor.name}...`);

      try {
        if (sensor.type === 'npm') {
          // NPM sensor test (uses get_data_modbus_v3.py --dry-run)
          const npmResult = await new Promise((resolve, reject) => {
            $.ajax({
              url: 'launcher.php?type=npm',
              dataType: 'json',
              method: 'GET',
              timeout: 15000,
              success: function(data) { resolve(data); },
              error: function(xhr, status, error) { reject(new Error(error || status)); }
            });
          });

          selfTestReport.rawResponses['NPM Sensor'] = JSON.stringify(npmResult, null, 2);
          addSelfTestLog(`NPM response: PM1=${npmResult.PM1}, PM2.5=${npmResult.PM25}, PM10=${npmResult.PM10}, status=${npmResult.npm_status_hex}`);

          // Decode npm_status flags
          const status = npmResult.npm_status !== undefined ? npmResult.npm_status : 0;

          if (status === 0xFF) {
            // 0xFF = no response = disconnected
            updateTestStatus(sensor.id, 'Failed', 'Capteur déconnecté', 'bg-danger');
            testsFailed++;
          } else {
            const statusFlags = {
              0x01: "Sleep mode",
              0x02: "Degraded mode",
              0x04: "Not ready",
              0x08: "Heater error",
              0x10: "THP sensor error",
              0x20: "Fan error",
              0x40: "Memory error",
              0x80: "Laser error"
            };
            const activeErrors = [];
            Object.entries(statusFlags).forEach(([mask, label]) => {
              if (status & mask) activeErrors.push(label);
            });

          if (activeErrors.length > 0) {
            updateTestStatus(sensor.id, 'Warning', `Status ${npmResult.npm_status_hex}: ${activeErrors.join(', ')}`, 'bg-warning');
            testsFailed++;
          } else if (npmResult.PM1 !== undefined && npmResult.PM25 !== undefined && npmResult.PM10 !== undefined) {
            updateTestStatus(sensor.id, 'Passed', `PM1: ${npmResult.PM1} | PM2.5: ${npmResult.PM25} | PM10: ${npmResult.PM10} µg/m³`, 'bg-success');
            testsPassed++;
          } else {
            updateTestStatus(sensor.id, 'Warning', 'Incomplete data received', 'bg-warning');
            testsFailed++;
          }
          } // end else (not 0xFF)

        } else if (sensor.type === 'BME280') {
          // BME280 sensor test
          const bme280Result = await new Promise((resolve, reject) => {
            $.ajax({
              url: 'launcher.php?type=BME280',
              dataType: 'text',
              method: 'GET',
              timeout: 15000,
              success: function(data) { resolve(data); },
              error: function(xhr, status, error) { reject(new Error(error || status)); }
            });
          });

          const bmeData = JSON.parse(bme280Result);
          selfTestReport.rawResponses['BME280 Sensor'] = JSON.stringify(bmeData, null, 2);
          addSelfTestLog(`BME280 response: temp=${bmeData.temp}, hum=${bmeData.hum}, press=${bmeData.press}`);

          if (bmeData.temp !== undefined && bmeData.hum !== undefined && bmeData.press !== undefined) {
            updateTestStatus(sensor.id, 'Passed', `${bmeData.temp}°C | ${bmeData.hum}% | ${bmeData.press} hPa`, 'bg-success');
            testsPassed++;
          } else {
            updateTestStatus(sensor.id, 'Warning', 'Incomplete data received', 'bg-warning');
            testsFailed++;
          }

        } else if (sensor.type === 'noise') {
          // NSRT MK4 noise sensor test (returns JSON)
          const noiseResult = await new Promise((resolve, reject) => {
            $.ajax({
              url: 'launcher.php?type=noise',
              dataType: 'json',
              method: 'GET',
              timeout: 15000,
              success: function(data) { resolve(data); },
              error: function(xhr, status, error) { reject(new Error(error || status)); }
            });
          });

          selfTestReport.rawResponses['Noise Sensor'] = JSON.stringify(noiseResult);
          addSelfTestLog(`Noise response: ${JSON.stringify(noiseResult)}`);

          if (noiseResult.error) {
            const noiseMsg = noiseResult.disconnected
              ? 'Capteur déconnecté — vérifiez le câblage USB'
              : noiseResult.error;
            updateTestStatus(sensor.id, 'Failed', noiseMsg, 'bg-danger');
            testsFailed++;
          } else if (noiseResult.LEQ > 0 && noiseResult.dBA > 0) {
            updateTestStatus(sensor.id, 'Passed', `LEQ: ${noiseResult.LEQ} dB | dB(A): ${noiseResult.dBA}`, 'bg-success');
            testsPassed++;
          } else {
            updateTestStatus(sensor.id, 'Warning', `Unexpected values: LEQ=${noiseResult.LEQ}, dBA=${noiseResult.dBA}`, 'bg-warning');
            testsFailed++;
          }

        } else if (sensor.type === 'envea') {
          // Envea sensor test - use the debug endpoint for all sensors
          const enveaResult = await new Promise((resolve, reject) => {
            $.ajax({
              url: 'launcher.php?type=envea_debug',
              dataType: 'text',
              method: 'GET',
              timeout: 30000,
              success: function(data) { resolve(data); },
              error: function(xhr, status, error) { reject(new Error(error || status)); }
            });
          });

          selfTestReport.rawResponses['Envea Sensors'] = enveaResult;
          addSelfTestLog(`Envea response: ${enveaResult.trim().substring(0, 200)}`);

          if (enveaResult.trim() !== '' && !enveaResult.toLowerCase().includes('error')) {
            updateTestStatus(sensor.id, 'Passed', 'Sensors responding', 'bg-success');
            testsPassed++;
          } else if (enveaResult.toLowerCase().includes('error')) {
            updateTestStatus(sensor.id, 'Failed', 'Sensor error detected', 'bg-danger');
            testsFailed++;
          } else {
            updateTestStatus(sensor.id, 'Failed', 'No data received', 'bg-danger');
            testsFailed++;
          }

        } else if (sensor.type === 'rtc') {
          // RTC DS3231 module test
          const rtcResult = await new Promise((resolve, reject) => {
            $.ajax({
              url: 'launcher.php?type=sys_RTC_module_time',
              dataType: 'json',
              method: 'GET',
              timeout: 10000,
              success: function(data) { resolve(data); },
              error: function(xhr, status, error) { reject(new Error(error || status)); }
            });
          });

          selfTestReport.rawResponses['RTC Module'] = JSON.stringify(rtcResult, null, 2);
          addSelfTestLog(`RTC response: ${JSON.stringify(rtcResult)}`);

          if (rtcResult.rtc_module_time === 'not connected') {
            updateTestStatus(sensor.id, 'Failed', 'RTC module not connected', 'bg-danger');
            testsFailed++;
          } else if (rtcResult.rtc_module_time) {
            // Compare RTC with browser time (more reliable than system time)
            const rtcDate = new Date(rtcResult.rtc_module_time + ' UTC');
            const browserDate = new Date();
            const timeDiff = Math.abs(Math.round((browserDate - rtcDate) / 1000));

            if (timeDiff <= 60) {
              updateTestStatus(sensor.id, 'Passed', `${rtcResult.rtc_module_time} (sync OK vs navigateur, ecart: ${timeDiff}s)`, 'bg-success');
              testsPassed++;
            } else {
              const minutes = Math.floor(timeDiff / 60);
              const label = minutes > 0 ? `${minutes}min ${timeDiff % 60}s` : `${timeDiff}s`;
              updateTestStatus(sensor.id, 'Warning', `${rtcResult.rtc_module_time} (desync vs navigateur: ${label})`, 'bg-warning');
              testsFailed++;
            }
          } else {
            updateTestStatus(sensor.id, 'Warning', 'Unexpected response', 'bg-warning');
            testsFailed++;
          }
        }
      } catch (error) {
        addSelfTestLog(`${sensor.name} test error: ${error.message}`);
        updateTestStatus(sensor.id, 'Failed', error.message, 'bg-danger');
        selfTestReport.rawResponses[`${sensor.name}`] = `ERROR: ${error.message}`;
        testsFailed++;
      }
    }

    // ═══════════════════════════════════════════════════════
    // COMMUNICATION TESTS - WiFi, Modem, SIM, Signal, Network
    // ═══════════════════════════════════════════════════════
    addSelfTestLog('');
    addSelfTestLog('────────────────────────────────────────────────────────');
    addSelfTestLog('COMMUNICATION TESTS');
    addSelfTestLog('────────────────────────────────────────────────────────');

    document.getElementById('comm_tests_separator').style.display = '';

    // Check WiFi / Network status (informational, no pass/fail)
    document.getElementById('selftest_status').innerHTML = `
      <div class="d-flex align-items-center text-primary">
        <div class="spinner-border spinner-border-sm me-2" role="status"></div>
        <span>Checking network status...</span>
      </div>`;

    updateTestStatus('wifi', 'Checking...', 'Getting network info...', 'bg-info');

    try {
      const wifiResponse = await new Promise((resolve, reject) => {
        $.ajax({
          url: 'launcher.php?type=wifi_status',
          dataType: 'json',
          method: 'GET',
          success: function(data) {
            addSelfTestLog(`WiFi status received`);
            // Store raw response
            selfTestReport.rawResponses['WiFi Status'] = JSON.stringify(data, null, 2);
            resolve(data);
          },
          error: function(xhr, status, error) {
            addSelfTestLog(`WiFi status error: ${error}`);
            selfTestReport.rawResponses['WiFi Status'] = `ERROR: ${error}`;
            reject(new Error(error));
          }
        });
      });

      // Log detailed WiFi info
      addSelfTestLog(`Mode: ${wifiResponse.mode}, SSID: ${wifiResponse.ssid}, IP: ${wifiResponse.ip}, Hostname: ${wifiResponse.hostname}`);

      if (wifiResponse.connected) {
        let modeLabel = '';
        let badgeClass = 'bg-info';

        if (wifiResponse.mode === 'hotspot') {
          modeLabel = 'Hotspot';
          badgeClass = 'bg-warning text-dark';
        } else if (wifiResponse.mode === 'wifi') {
          modeLabel = 'WiFi';
          badgeClass = 'bg-info';
        } else if (wifiResponse.mode === 'ethernet') {
          modeLabel = 'Ethernet';
          badgeClass = 'bg-info';
        }

        const detailText = `${wifiResponse.ssid} | ${wifiResponse.ip} | ${wifiResponse.hostname}.local`;
        updateTestStatus('wifi', modeLabel, detailText, badgeClass);
      } else {
        updateTestStatus('wifi', 'Disconnected', 'No network connection', 'bg-secondary');
      }
    } catch (error) {
      updateTestStatus('wifi', 'Error', error.message, 'bg-secondary');
    }

    await delaySelfTest(500);

    // Enable config mode
    document.getElementById('selftest_status').innerHTML = `
      <div class="d-flex align-items-center text-primary">
        <div class="spinner-border spinner-border-sm me-2" role="status"></div>
        <span>Enabling configuration mode...</span>
      </div>`;

    await setConfigMode(true);

    // Wait for SARA script to release the port (2 seconds should be enough)
    addSelfTestLog('Waiting for modem port to be available...');
    await delaySelfTest(2000);

    // Test Modem Connection (ATI)
    document.getElementById('selftest_status').innerHTML = `
      <div class="d-flex align-items-center text-primary">
        <div class="spinner-border spinner-border-sm me-2" role="status"></div>
        <span>Testing modem connection...</span>
      </div>`;

    updateTestStatus('modem', 'Testing...', 'Sending ATI command...', 'bg-info');

    try {
      const modemResponse = await sendATCommand('ATI', 5);

      if (modemResponse.includes('OK') && (modemResponse.toUpperCase().includes('SARA-R5') || modemResponse.toUpperCase().includes('SARA-R4'))) {
        // Extract model
        const modelMatch = modemResponse.match(/SARA-R[45]\d*[A-Z]*-\d+[A-Z]*-\d+/i);
        const model = modelMatch ? modelMatch[0] : 'SARA module';
        updateTestStatus('modem', 'Passed', `Model: ${model}`, 'bg-success');
        testsPassed++;
      } else if (modemResponse.includes('OK')) {
        updateTestStatus('modem', 'Passed', 'Modem responding', 'bg-success');
        testsPassed++;
      } else {
        updateTestStatus('modem', 'Failed', 'No valid response', 'bg-danger');
        testsFailed++;
      }
    } catch (error) {
      updateTestStatus('modem', 'Failed', error.message, 'bg-danger');
      testsFailed++;
    }

    // Delay between AT commands
    await delaySelfTest(1000);

    // Test SIM Card (AT+CCID?)
    document.getElementById('selftest_status').innerHTML = `
      <div class="d-flex align-items-center text-primary">
        <div class="spinner-border spinner-border-sm me-2" role="status"></div>
        <span>Testing SIM card...</span>
      </div>`;

    updateTestStatus('sim', 'Testing...', 'Sending AT+CCID? command...', 'bg-info');

    try {
      const simResponse = await sendATCommand('AT+CCID?', 5);

      const ccidMatch = simResponse.match(/\+CCID:\s*(\d{18,22})/);
      if (simResponse.includes('OK') && ccidMatch) {
        const iccid = ccidMatch[1];
        // Show last 4 digits only for privacy
        const maskedIccid = '****' + iccid.slice(-4);
        updateTestStatus('sim', 'Passed', `ICCID: ...${maskedIccid}`, 'bg-success');
        testsPassed++;
      } else if (simResponse.includes('ERROR')) {
        updateTestStatus('sim', 'Failed', 'SIM card not detected', 'bg-danger');
        testsFailed++;
      } else {
        updateTestStatus('sim', 'Warning', 'Unable to read ICCID', 'bg-warning');
        testsFailed++;
      }
    } catch (error) {
      updateTestStatus('sim', 'Failed', error.message, 'bg-danger');
      testsFailed++;
    }

    // Delay between AT commands
    await delaySelfTest(1000);

    // Test Signal Strength (AT+CSQ)
    document.getElementById('selftest_status').innerHTML = `
      <div class="d-flex align-items-center text-primary">
        <div class="spinner-border spinner-border-sm me-2" role="status"></div>
        <span>Testing signal strength...</span>
      </div>`;

    updateTestStatus('signal', 'Testing...', 'Sending AT+CSQ command...', 'bg-info');

    try {
      const signalResponse = await sendATCommand('AT+CSQ', 5);

      const csqMatch = signalResponse.match(/\+CSQ:\s*(\d+),(\d+)/);
      if (signalResponse.includes('OK') && csqMatch) {
        const signalPower = parseInt(csqMatch[1]);

        if (signalPower === 99) {
          updateTestStatus('signal', 'Failed', 'No signal detected', 'bg-danger');
          testsFailed++;
        } else if (signalPower === 0) {
          updateTestStatus('signal', 'Warning', 'Very poor signal (0/31)', 'bg-warning');
          testsFailed++;
        } else if (signalPower <= 24) {
          updateTestStatus('signal', 'Passed', `Poor signal (${signalPower}/31)`, 'bg-success');
          testsPassed++;
        } else if (signalPower <= 26) {
          updateTestStatus('signal', 'Passed', `Good signal (${signalPower}/31)`, 'bg-success');
          testsPassed++;
        } else if (signalPower <= 28) {
          updateTestStatus('signal', 'Passed', `Very good signal (${signalPower}/31)`, 'bg-success');
          testsPassed++;
        } else {
          updateTestStatus('signal', 'Passed', `Excellent signal (${signalPower}/31)`, 'bg-success');
          testsPassed++;
        }
      } else if (signalResponse.includes('ERROR')) {
        updateTestStatus('signal', 'Failed', 'Unable to read signal', 'bg-danger');
        testsFailed++;
      } else {
        updateTestStatus('signal', 'Warning', 'Unexpected response', 'bg-warning');
        testsFailed++;
      }
    } catch (error) {
      updateTestStatus('signal', 'Failed', error.message, 'bg-danger');
      testsFailed++;
    }

    // Delay between AT commands
    await delaySelfTest(1000);

    // Test Network Connection (AT+COPS?)
    document.getElementById('selftest_status').innerHTML = `
      <div class="d-flex align-items-center text-primary">
        <div class="spinner-border spinner-border-sm me-2" role="status"></div>
        <span>Testing network connection...</span>
      </div>`;

    updateTestStatus('network', 'Testing...', 'Sending AT+COPS? command...', 'bg-info');

    try {
      // Load operators data for network name lookup
      let opData = null;
      try {
        opData = await loadOperatorsDataSelfTest();
      } catch (e) {
        addSelfTestLog('Warning: Could not load operators data');
      }

      const networkResponse = await sendATCommand('AT+COPS?', 5);

      const copsMatch = networkResponse.match(/\+COPS:\s*(\d+)(?:,(\d+),"?([^",]+)"?,(\d+))?/);
      if (networkResponse.includes('OK') && copsMatch) {
        const mode = copsMatch[1];
        const oper = copsMatch[3];
        const act = copsMatch[4];

        if (oper) {
          // Get operator name from lookup table
          let operatorName = oper;
          if (opData && opData.operators && opData.operators[oper]) {
            operatorName = opData.operators[oper].name;
          }

          // Get access technology
          let actDesc = 'Unknown';
          if (opData && opData.accessTechnology && opData.accessTechnology[act]) {
            actDesc = opData.accessTechnology[act];
          }

          updateTestStatus('network', 'Passed', `${operatorName} (${actDesc})`, 'bg-success');
          testsPassed++;
        } else {
          updateTestStatus('network', 'Warning', 'Not registered to network', 'bg-warning');
          testsFailed++;
        }
      } else if (networkResponse.includes('ERROR')) {
        updateTestStatus('network', 'Failed', 'Unable to get network info', 'bg-danger');
        testsFailed++;
      } else {
        updateTestStatus('network', 'Warning', 'Unexpected response', 'bg-warning');
        testsFailed++;
      }
    } catch (error) {
      updateTestStatus('network', 'Failed', error.message, 'bg-danger');
      testsFailed++;
    }

  } catch (error) {
    addSelfTestLog(`Test sequence error: ${error.message}`);
  } finally {
    // Always disable config mode at the end
    document.getElementById('selftest_status').innerHTML = `
      <div class="d-flex align-items-center text-primary">
        <div class="spinner-border spinner-border-sm me-2" role="status"></div>
        <span>Disabling configuration mode...</span>
      </div>`;

    try {
      await delaySelfTest(500);
      await setConfigMode(false);
    } catch (error) {
      addSelfTestLog(`Warning: Failed to disable config mode: ${error.message}`);
    }

    // Show final status
    const totalTests = testsPassed + testsFailed;
    let statusClass, statusIcon, statusText;

    if (testsFailed === 0) {
      statusClass = 'text-success';
      statusIcon = '✓';
      statusText = 'All tests passed';
    } else if (testsPassed === 0) {
      statusClass = 'text-danger';
      statusIcon = '✗';
      statusText = 'All tests failed';
    } else {
      statusClass = 'text-warning';
      statusIcon = '!';
      statusText = 'Some tests failed';
    }

    document.getElementById('selftest_status').innerHTML = `
      <div class="d-flex align-items-center ${statusClass}">
        <span class="fs-4 me-2">${statusIcon}</span>
        <span><strong>${statusText}</strong></span>
      </div>`;

    document.getElementById('selftest_summary').innerHTML = `
      <span class="badge bg-success me-1">${testsPassed} passed</span>
      <span class="badge bg-danger">${testsFailed} failed</span>`;

    // Store summary in report
    selfTestReport.summary = {
      passed: testsPassed,
      failed: testsFailed,
      status: statusText
    };

    // Enable buttons
    document.getElementById('selfTestCloseBtn').disabled = false;
    document.getElementById('selfTestDoneBtn').disabled = false;
    document.getElementById('selfTestCopyBtn').disabled = false;
    document.querySelectorAll('.btn_selfTest').forEach(btn => btn.disabled = false);

    addSelfTestLog('Self test completed.');
    addSelfTestLog('Click "Copy Report" to share results with support.');
  }
}

function generateReport() {
  // Build formatted report
  let report = `===============================================================
             NEBULEAIR PRO 4G - SELF TEST REPORT
===============================================================

DEVICE INFORMATION
------------------
Device ID:      ${selfTestReport.deviceId || 'Unknown'}
Device Name:    ${selfTestReport.deviceName || 'Unknown'}
Modem Version:  ${selfTestReport.modemVersion || 'Unknown'}
System Time:    ${selfTestReport.systemTime || 'Unknown'}
Report Date:    ${selfTestReport.timestamp}
GPS Location:   ${selfTestReport.latitude || 'N/A'}, ${selfTestReport.longitude || 'N/A'}

===============================================================
                       TEST RESULTS
===============================================================

`;

  // Add test results (sensors first, then communication)
  const testNames = {
    npm: 'NextPM (Particles)',
    bme280: 'BME280 (Temp/Hum)',
    noise: 'Noise Sensor',
    envea: 'Envea (Gas Sensors)',
    rtc: 'RTC Module (DS3231)',
    wifi: 'WiFi/Network',
    modem: 'Modem Connection',
    sim: 'SIM Card',
    signal: 'Signal Strength',
    network: 'Network Connection'
  };

  for (const [testId, name] of Object.entries(testNames)) {
    if (selfTestReport.results[testId]) {
      const result = selfTestReport.results[testId];
      const statusIcon = result.status === 'Passed' ? '[OK]' :
                        result.status === 'Failed' ? '[FAIL]' :
                        result.status.includes('Hotspot') || result.status.includes('WiFi') || result.status.includes('Ethernet') ? '[INFO]' : '[WARN]';
      report += `${statusIcon} ${name}
       Status: ${result.status}
       Detail: ${result.detail}

`;
    }
  }

  // Add summary
  if (selfTestReport.summary) {
    report += `===============================================================
                          SUMMARY
===============================================================

Passed: ${selfTestReport.summary.passed}
Failed: ${selfTestReport.summary.failed}
Status: ${selfTestReport.summary.status}

`;
  }

  // Add raw AT responses
  report += `===============================================================
                     RAW AT RESPONSES
===============================================================

`;

  for (const [command, response] of Object.entries(selfTestReport.rawResponses)) {
    report += `--- ${command} ---
${response}

`;
  }

  // Add full logs
  report += `===============================================================
                       DETAILED LOGS
===============================================================

${document.getElementById('selftest_logs').textContent}

===============================================================
         END OF REPORT - Generated by NebuleAir Pro 4G
===============================================================
`;

  return report;
}

function openShareReportModal() {
  // Generate the report
  const report = generateReport();

  // Put report in textarea
  document.getElementById('shareReportText').value = report;

  // Open the share modal
  const shareModal = new bootstrap.Modal(document.getElementById('shareReportModal'));
  shareModal.show();
}

function selectAllReportText() {
  const textarea = document.getElementById('shareReportText');
  textarea.select();
  textarea.setSelectionRange(0, textarea.value.length); // For mobile devices
}

function downloadReport() {
  const report = generateReport();

  // Create filename with device ID
  const deviceId = selfTestReport.deviceId || 'unknown';
  const date = new Date().toISOString().slice(0, 10);
  const filename = `logs_nebuleair_${deviceId}_${date}.txt`;

  // Create blob and download
  const blob = new Blob([report], { type: 'text/plain;charset=utf-8' });
  const url = URL.createObjectURL(blob);

  const a = document.createElement('a');
  a.href = url;
  a.download = filename;
  document.body.appendChild(a);
  a.click();

  // Cleanup
  setTimeout(function() {
    document.body.removeChild(a);
    URL.revokeObjectURL(url);
  }, 100);
}

// Load the self-test modal HTML into the page
function initSelfTestModal() {
  fetch('selftest-modal.html')
    .then(response => response.text())
    .then(html => {
      // Insert modal HTML before </body>
      const container = document.createElement('div');
      container.id = 'selftest-modal-container';
      container.innerHTML = html;
      document.body.appendChild(container);
    })
    .catch(error => console.error('Error loading selftest modal:', error));
}

// Auto-init when DOM is ready
document.addEventListener('DOMContentLoaded', initSelfTestModal);
