// Nithic Security Popup — Dual-Shield Per-Tab Status
// Fetches per-tab analysis + session-wide stats

class PopupUI {
  constructor() {
    this.tabStatus = null;
    this.sessionStats = { totalAnalyses: 0, blockedUrls: 0 };
    this.enterpriseStatus = null;
    this.isInitialized = false;
    this.refreshInterval = null;
  }

  async initialize() {
    if (this.isInitialized) return;

    try {
      // Fetch all data in parallel
      await Promise.all([
        this.fetchTabStatus(),
        this.fetchSessionStats(),
        this.fetchEnterpriseStatus()
      ]);

      this.renderTabStatus();
      this.renderSessionStats();
      this.renderEnterprise();
      this.setupEventListeners();
      this.startAutoRefresh();

      // Set version from manifest
      try {
        const manifest = chrome.runtime.getManifest();
        const versionEl = document.getElementById('version');
        if (versionEl) versionEl.textContent = `v${manifest.version}`;
      } catch (e) { /* ignore */ }

      this.isInitialized = true;
    } catch (error) {
      console.error('Popup init error:', error);
    }
  }

  // --- Data fetching ---

  async fetchTabStatus() {
    try {
      const response = await chrome.runtime.sendMessage({ type: 'getTabStatus' });
      if (response && !response.error) {
        this.tabStatus = response;
      }
    } catch (error) {
      console.warn('Tab status unavailable:', error);
    }
  }

  async fetchSessionStats() {
    try {
      const [stats, telemetry] = await Promise.all([
        chrome.runtime.sendMessage({ type: 'getStats' }),
        chrome.runtime.sendMessage({ type: 'getTelemetry' })
      ]);
      this.sessionStats = {
        totalAnalyses: telemetry?.session?.totalAnalyses || 0,
        blockedUrls: stats?.blockedUrls || 0
      };
    } catch (error) {
      console.warn('Session stats unavailable:', error);
    }
  }

  async fetchEnterpriseStatus() {
    try {
      const response = await chrome.runtime.sendMessage({ type: 'getEnterpriseStatus' });
      if (response) {
        this.enterpriseStatus = response;
      }
    } catch (error) {
      console.warn('Enterprise status unavailable:', error);
    }
  }

  // --- Rendering ---

  renderTabStatus() {
    const status = this.tabStatus;

    // Tab URL bar
    const tabUrlEl = document.getElementById('tab-url');
    const tabDotEl = document.getElementById('tab-status-dot');
    const tabLabelEl = document.getElementById('tab-status-label');

    if (!status || !status.url) {
      if (tabUrlEl) tabUrlEl.textContent = 'No active tab';
      if (tabDotEl) tabDotEl.classList.add('inactive');
      if (tabLabelEl) {
        tabLabelEl.textContent = 'Inactive';
        tabLabelEl.classList.add('inactive');
      }
      return;
    }

    // Display URL (truncate domain)
    try {
      const urlObj = new URL(status.url);
      if (tabUrlEl) tabUrlEl.textContent = urlObj.hostname + urlObj.pathname.replace(/\/$/, '');
    } catch {
      if (tabUrlEl) tabUrlEl.textContent = status.url.substring(0, 50);
    }

    // Protection status
    const isWebPage = status.url.startsWith('http');
    if (tabDotEl) tabDotEl.classList.toggle('inactive', !isWebPage);
    if (tabLabelEl) {
      tabLabelEl.textContent = isWebPage ? 'Active' : 'N/A';
      tabLabelEl.classList.toggle('inactive', !isWebPage);
    }

    // --- Security Shield ---
    this.renderSecurityShield(status.security, status);

    // --- AI Content Shield ---
    this.renderAIShield(status.aiContent);
  }

  renderSecurityShield(security, fullStatus) {
    if (!security) return;

    // Overall pill
    const overallEl = document.getElementById('security-overall');
    if (overallEl) {
      const labels = { safe: 'Safe', warning: 'Warning', danger: 'Danger', unknown: 'Unknown' };
      overallEl.textContent = labels[security.overall] || 'Unknown';
      overallEl.className = `status-pill ${security.overall || 'unknown'}`;
    }

    // Summary — show detection count if any, otherwise show sub-indicator levels
    const summaryEl = document.getElementById('security-summary');
    if (summaryEl) {
      const count = fullStatus?.findingsCount || 0;
      if (count > 0) {
        const riskLabel = this.capitalize(fullStatus.riskLevel || 'unknown');
        summaryEl.textContent = `${count} finding${count !== 1 ? 's' : ''} \u00b7 ${riskLabel} risk`;
      } else {
        const chipParts = [];
        if (security.connection) chipParts.push(this.capitalize(security.connection.level));
        if (security.reputation) chipParts.push(this.capitalize(security.reputation.level));
        if (security.fingerprint) chipParts.push(this.capitalize(security.fingerprint.level));
        if (security.behavior) chipParts.push(this.capitalize(security.behavior.level));
        summaryEl.textContent = chipParts.join(' \u00b7 ');
      }
    }

    // Connection sub-indicator
    if (security.connection) {
      this.setSubIndicator('connection', security.connection.level, security.connection.details);
    }

    // Reputation sub-indicator
    if (security.reputation) {
      this.setSubIndicator('reputation', security.reputation.level, security.reputation.details);
    }

    // Fingerprint sub-indicator
    if (security.fingerprint) {
      this.setSubIndicator('fingerprint', security.fingerprint.level, security.fingerprint.details);
      // Render expandable tech + CVE panel
      this.renderTechCvePanel(security.fingerprint);
    }

    // Behavior sub-indicator
    if (security.behavior) {
      this.setSubIndicator('behavior', security.behavior.level, security.behavior.details);
      // Toggle monitoring badge visibility
      const badge = document.getElementById('monitoring-badge');
      if (badge) {
        badge.style.display = security.behavior.monitoring ? 'flex' : 'none';
      }
      // Toggle shimmer class
      const behaviorRow = document.getElementById('sub-behavior');
      if (behaviorRow) {
        behaviorRow.classList.toggle('behavior-monitoring', security.behavior.monitoring);
      }
    }
  }

  renderAIShield(aiContent) {
    if (!aiContent) return;
    // Hand the on-page passive-scan summary to the settings-row renderer,
    // which also factors in the toggle state.
    _nsLastAiContent = aiContent;
    nsRenderOnPageRow();

    // Overall pill
    const overallEl = document.getElementById('ai-overall');
    if (overallEl) {
      const labels = { safe: 'Clear', danger: 'AI Detected', warning: 'Warning', unknown: 'N/A' };
      overallEl.textContent = labels[aiContent.overall] || 'N/A';
      overallEl.className = `status-pill ${aiContent.overall === 'danger' ? 'detected' : aiContent.overall || 'unknown'}`;
    }

    // Text Analysis row is owned by nsRenderOnPageRow() (called above) — it
    // folds together the toggle state, on-device engine status, and live
    // page-scan counts. No separate clipboard rendering here.

    // Images
    if (aiContent.images) {
      const statusEl = document.getElementById('ai-image-status');
      const detailEl = document.getElementById('ai-image-detail');
      if (aiContent.images.level === 'unknown') {
        if (statusEl) { statusEl.textContent = 'N/A'; statusEl.className = 'sub-status na'; }
        if (detailEl) detailEl.textContent = 'No images scanned yet';
      } else if (aiContent.images.level === 'danger') {
        const parts = [];
        if (aiContent.images.aiCount > 0) parts.push(`${aiContent.images.aiCount} AI`);
        if (aiContent.images.manipulated > 0) parts.push(`${aiContent.images.manipulated} manipulated`);
        if (statusEl) { statusEl.textContent = 'Flagged'; statusEl.className = 'sub-status danger'; }
        if (detailEl) detailEl.textContent = `${aiContent.images.count} scanned — ${parts.join(', ')}`;
      } else if (aiContent.images.level === 'warning') {
        if (statusEl) { statusEl.textContent = 'Uncertain'; statusEl.className = 'sub-status warning'; }
        if (detailEl) detailEl.textContent = `${aiContent.images.count} scanned — some inconclusive`;
      } else {
        if (statusEl) { statusEl.textContent = 'Clean'; statusEl.className = 'sub-status safe'; }
        if (detailEl) detailEl.textContent = `${aiContent.images.count} image(s) — all authentic`;
      }
    }

    // Video
    if (aiContent.video) {
      const statusEl = document.getElementById('ai-video-status');
      const detailEl = document.getElementById('ai-video-detail');
      if (aiContent.video.level === 'unknown') {
        if (statusEl) { statusEl.textContent = 'N/A'; statusEl.className = 'sub-status na'; }
        if (detailEl) detailEl.textContent = 'Coming soon';
      } else {
        if (statusEl) { statusEl.textContent = this.capitalize(aiContent.video.level); statusEl.className = `sub-status ${aiContent.video.level}`; }
        if (detailEl) detailEl.textContent = `${aiContent.video.count} clip(s) analyzed`;
      }
    }

    // Authenticity score
    const fillEl = document.getElementById('authenticity-fill');
    const valueEl = document.getElementById('authenticity-value');
    if (aiContent.authenticityScore != null) {
      const score = Math.round(aiContent.authenticityScore);
      if (fillEl) {
        fillEl.style.width = `${score}%`;
        fillEl.className = `meter-fill ${score >= 70 ? 'high' : score >= 40 ? 'medium' : 'low'}`;
      }
      if (valueEl) valueEl.textContent = `${score}%`;
    } else {
      if (fillEl) { fillEl.style.width = '0%'; fillEl.className = 'meter-fill'; }
      if (valueEl) valueEl.textContent = '\u2014';
    }
  }

  renderSessionStats() {
    const analysesEl = document.getElementById('session-analyses');
    const blockedEl = document.getElementById('session-blocked');
    if (analysesEl) analysesEl.textContent = this.sessionStats.totalAnalyses;
    if (blockedEl) blockedEl.textContent = this.sessionStats.blockedUrls;
  }

  renderEnterprise() {
    if (!this.enterpriseStatus || !this.enterpriseStatus.enterpriseMode) return;

    document.getElementById('enterprise-section').style.display = 'block';

    if (this.enterpriseStatus.mdm) {
      this.setEnterpriseStatus('mdm', this.enterpriseStatus.mdm.enrollmentStatus === 'managed');
    }
    if (this.enterpriseStatus.adminConsole) {
      this.setEnterpriseStatus('admin', this.enterpriseStatus.adminConsole.connected);
    }
    if (this.enterpriseStatus.siem) {
      this.setEnterpriseStatus('siem', this.enterpriseStatus.siem.enabled);
    }
    if (this.enterpriseStatus.clickhouse) {
      this.setEnterpriseStatus('clickhouse', this.enterpriseStatus.clickhouse.enabled);
    }
  }

  // --- Event listeners ---

  setupEventListeners() {
    // Shield expand/collapse toggles
    const securityHeader = document.getElementById('security-header');
    const aiHeader = document.getElementById('ai-header');
    const securityShield = document.getElementById('security-shield');
    const aiShield = document.getElementById('ai-shield');

    if (securityHeader && securityShield) {
      securityHeader.addEventListener('click', () => {
        securityShield.classList.toggle('expanded');
      });
    }

    if (aiHeader && aiShield) {
      aiHeader.addEventListener('click', () => {
        aiShield.classList.toggle('expanded');
      });
    }

    // Fingerprint row expand/collapse for tech+CVE panel
    const fpRow = document.getElementById('sub-fingerprint');
    const techPanel = document.getElementById('tech-cve-panel');
    if (fpRow && techPanel) {
      fpRow.addEventListener('click', () => {
        const isOpen = fpRow.classList.toggle('open');
        techPanel.style.display = isOpen ? 'block' : 'none';
      });
    }

    // Techniques button
    const techniquesBtn = document.getElementById('open-techniques-btn');
    if (techniquesBtn) {
      techniquesBtn.addEventListener('click', () => {
        chrome.tabs.create({ url: chrome.runtime.getURL('techniques.html') });
      });
    }

    // Settings button
    const settingsBtn = document.getElementById('open-settings-btn');
    if (settingsBtn) {
      settingsBtn.addEventListener('click', () => {
        chrome.runtime.openOptionsPage();
      });
    }

    // Live stats updates from background
    chrome.runtime.onMessage.addListener((message) => {
      if (message.type === 'statsUpdated') {
        this.sessionStats.blockedUrls = message.data.blockedUrls || 0;
        this.renderSessionStats();
      }
    });
  }

  startAutoRefresh() {
    // Refresh tab status every 3 seconds (fast for behavioral monitoring feel)
    this.refreshInterval = setInterval(async () => {
      await Promise.all([
        this.fetchTabStatus(),
        this.fetchSessionStats()
      ]);
      this.renderTabStatus();
      this.renderSessionStats();
    }, 3000);
  }

  // --- Helpers ---

  setSubIndicator(name, level, detail) {
    const statusEl = document.getElementById(`${name}-status`);
    const detailEl = document.getElementById(`${name}-detail`);
    if (statusEl) {
      statusEl.textContent = this.capitalize(level);
      statusEl.className = `sub-status ${level || 'unknown'}`;
    }
    if (detailEl) {
      detailEl.textContent = detail || '';
    }
  }

  renderTechCvePanel(fpData) {
    const panel = document.getElementById('tech-cve-panel');
    const techListEl = document.getElementById('tech-list');
    const divider = document.getElementById('cve-divider');
    const cveHeader = document.getElementById('cve-section-header');
    const cveCounts = document.getElementById('cve-section-counts');
    const cveContainer = document.getElementById('cve-list-container');
    const cveList = document.getElementById('cve-list');
    if (!panel) return;

    const technologies = fpData.technologies || [];
    const vulnData = fpData.vulnerabilities;
    const vulns = vulnData?.vulns || [];
    const summary = vulnData?.summary;

    const fpRow = document.getElementById('sub-fingerprint');

    // Nothing to show — remove expandable state
    if (technologies.length === 0 && vulns.length === 0) {
      panel.style.display = 'none';
      if (fpRow) {
        fpRow.classList.remove('expandable', 'open');
        const hint = fpRow.querySelector('.expand-hint');
        if (hint) hint.remove();
      }
      return;
    }

    // Mark fingerprint row as expandable (panel stays hidden until clicked)
    if (fpRow && !fpRow.classList.contains('expandable')) {
      fpRow.classList.add('expandable');
      // Add expand arrow hint if not already there
      if (!fpRow.querySelector('.expand-hint')) {
        const hint = document.createElement('span');
        hint.className = 'expand-hint';
        hint.textContent = '\u25B8'; // right-pointing triangle
        fpRow.querySelector('.sub-indicator-left')?.appendChild(hint);
      }
    }

    // Keep panel hidden — user clicks to expand
    // (don't override if already open from a previous click)
    if (!fpRow?.classList.contains('open')) {
      panel.style.display = 'none';
    }

    // Update fingerprint status pill with CVE count
    const statusEl = document.getElementById('fingerprint-status');
    if (statusEl && summary?.total_cves > 0) {
      statusEl.textContent = `${summary.total_cves} CVE${summary.total_cves !== 1 ? 's' : ''}`;
    }

    // --- Tech chips ---
    if (techListEl) {
      techListEl.innerHTML = '';
      for (const tech of technologies) {
        const chip = document.createElement('span');
        // Color class based on CVE severity
        let colorClass = 'unknown'; // gray — no CVE data checked
        if (vulnData) {
          // We have CVE data: color by worst severity, or green if clean
          colorClass = tech.worstSeverity || 'safe';
        }
        chip.className = `tech-chip ${colorClass}`;
        chip.title = tech.category + (tech.cveCount ? ` \u2022 ${tech.cveCount} CVE(s)` : '');

        const nameSpan = document.createElement('span');
        nameSpan.className = 'tech-name';
        nameSpan.textContent = tech.name;
        chip.appendChild(nameSpan);

        if (tech.version) {
          const verSpan = document.createElement('span');
          verSpan.className = 'tech-ver';
          verSpan.textContent = tech.version;
          chip.appendChild(verSpan);
        }

        if (tech.cveCount) {
          const badge = document.createElement('span');
          badge.className = 'tech-cve-badge';
          badge.textContent = tech.cveCount;
          chip.appendChild(badge);
        }

        techListEl.appendChild(chip);
      }
    }

    // --- CVE section ---
    if (vulns.length === 0) {
      if (divider) divider.style.display = 'none';
      if (cveHeader) cveHeader.style.display = 'none';
      if (cveContainer) cveContainer.style.display = 'none';
      return;
    }

    if (divider) divider.style.display = 'block';
    if (cveHeader) cveHeader.style.display = 'flex';
    if (cveContainer) cveContainer.style.display = 'block';

    // Severity summary badges
    if (cveCounts && summary) {
      cveCounts.innerHTML = '';
      if (summary.critical > 0) cveCounts.innerHTML += `<span class="cnt-crit">${summary.critical}C</span>`;
      if (summary.high > 0) cveCounts.innerHTML += `<span class="cnt-high">${summary.high}H</span>`;
      if (summary.medium > 0) cveCounts.innerHTML += `<span class="cnt-med">${summary.medium}M</span>`;
      if (summary.low > 0) cveCounts.innerHTML += `<span class="cnt-low">${summary.low}L</span>`;
    }

    // CVE items
    if (cveList) {
      cveList.innerHTML = '';
      for (const v of vulns) {
        const item = document.createElement('div');
        item.className = 'cve-item';
        item.title = v.description || v.title || '';

        const badge = document.createElement('span');
        badge.className = `cve-severity ${(v.severity || 'medium').toLowerCase()}`;
        badge.textContent = (v.severity || 'MED').substring(0, 4).toUpperCase();

        const id = document.createElement('span');
        id.className = 'cve-id';
        id.textContent = v.cve_id || '';

        const title = document.createElement('span');
        title.className = 'cve-title';
        title.textContent = v.title || v.cve_id || '';

        item.appendChild(badge);
        item.appendChild(id);
        item.appendChild(title);
        cveList.appendChild(item);
      }
    }
  }

  setEnterpriseStatus(service, connected) {
    const dot = document.getElementById(`${service}-status-dot`);
    const text = document.getElementById(`${service}-status`);
    if (dot && text) {
      dot.classList.toggle('connected', connected);
      dot.classList.toggle('disconnected', !connected);
      text.textContent = connected ? 'Connected' : 'Disconnected';
    }
  }

  capitalize(str) {
    if (!str) return '';
    return str.charAt(0).toUpperCase() + str.slice(1);
  }
}

// Initialize
const popup = new PopupUI();

if (document.readyState === 'loading') {
  document.addEventListener('DOMContentLoaded', () => popup.initialize());
} else {
  popup.initialize();
}

// ============================================
// Settings toggles (snooze + per-modality)
// ============================================
// Detection always runs server-side; these toggles control:
//   - overlays.enabled        : visual indicators on the page
//   - detection.{text,image,video} : whether the content script even queues
//                                    a scan for that modality
const NS_DEFAULTS = {
  // overlays.enabled = master "Show detection overlays"; text/image/textDetail/
  // minConfidence are the granular controls (Settings → Overlays).
  overlays: { enabled: true, text: true, image: true, textDetail: 'detailed', minConfidence: 0 },
  // text now drives the on-page passive scan (+ clipboard). engine: local |
  // cloud | hybrid.
  detection: { image: true, text: true, video: true, engine: 'local', contentRules: true }
};

async function nsLoadSettings() {
  try {
    const result = await chrome.storage.local.get('nithicSettings');
    const s = result.nithicSettings || {};
    return {
      overlays:  { ...NS_DEFAULTS.overlays,  ...(s.overlays  || {}) },
      detection: { ...NS_DEFAULTS.detection, ...(s.detection || {}) }
    };
  } catch (_) {
    return JSON.parse(JSON.stringify(NS_DEFAULTS));
  }
}

async function nsSaveSettings(patch) {
  const current = await nsLoadSettings();
  const next = {
    overlays:  { ...current.overlays,  ...(patch.overlays  || {}) },
    detection: { ...current.detection, ...(patch.detection || {}) }
  };
  await chrome.storage.local.set({ nithicSettings: next });
  return next;
}

function nsApplyToggleState(button, isOn) {
  if (!button) return;
  button.classList.toggle('on', !!isOn);
  button.setAttribute('aria-pressed', String(!!isOn));
}

// Text Analysis row state. The status chip + detail line reflect the toggle
// (off = idle), the on-device engine state (download/ready), and live per-tab
// scan counts. _nsTextEnabled mirrors detection.text.
let _nsTextEnabled = null;           // null = not yet loaded
let _nsLastAiContent = null;         // last aiContent from getTabStatus
let _nsEngineStatus = null;          // { engine, state, device, progress, error, available }
let _nsEnginePoll = null;

function nsEngineSuffix() {
  const e = _nsEngineStatus;
  if (!e) return '';
  if (e.engine === 'cloud') return ' · cloud';
  // local
  if (e.device === 'webgpu') return ' · on-device (GPU)';
  if (e.device === 'wasm')   return ' · on-device';
  return ' · on-device';
}

function nsRenderOnPageRow() {
  const statusEl = document.getElementById('ai-text-status');
  const detailEl = document.getElementById('ai-text-detail');
  if (!statusEl || !detailEl) return;
  const op = _nsLastAiContent && _nsLastAiContent.textOnPage;
  const eng = _nsEngineStatus;

  if (_nsTextEnabled === false) {
    statusEl.textContent = 'Off';
    statusEl.className = 'sub-status na';
    detailEl.textContent = 'Turn on to analyze AI-written text on pages you visit';
    return;
  }

  // First-run model download (local engine only).
  if (eng && eng.engine === 'local' && eng.state === 'loading') {
    statusEl.textContent = 'Loading';
    statusEl.className = 'sub-status warning';
    const pct = eng.progress ? ` ${eng.progress}%` : '';
    // "cached" means weights are already on disk — so this is a load, not a
    // fresh ~153MB download.
    detailEl.textContent = eng.cached
      ? `Loading on-device model…${pct}`
      : `Downloading private model…${pct} (one time, ~150MB)`;
    return;
  }
  if (eng && eng.engine === 'local' && eng.state === 'error') {
    statusEl.textContent = 'Error';
    statusEl.className = 'sub-status danger';
    detailEl.textContent = 'On-device model failed to load — see console';
    return;
  }
  // Local engine, idle (no scan in flight on this tab yet).
  if (eng && eng.engine === 'local' && eng.state === 'idle' && !(op && op.count > 0)) {
    statusEl.textContent = eng.cached ? 'Ready' : 'On';
    statusEl.className = 'sub-status safe';
    detailEl.textContent = eng.cached
      ? `On-device model ready${nsEngineSuffix()}`
      : 'On — analyzes pages you visit (model downloads on first use)';
    return;
  }

  // Enabled + engine ready (or status unknown — treat as active).
  const analyzing = op && op.analyzing ? op.analyzing : 0;
  const found = op && op.identified ? op.identified : 0;
  const flagged = op && op.aiCount ? op.aiCount : 0;
  const scanned = op && op.count ? op.count : 0;

  if (analyzing > 0) {
    // A batch is in flight — show live progress.
    statusEl.textContent = 'Analyzing';
    statusEl.className = 'sub-status warning';
    const flaggedPart = flagged > 0 ? ` · ${flagged} flagged` : '';
    detailEl.textContent = `Analyzing ${analyzing} of ${found} passage${found === 1 ? '' : 's'}${flaggedPart}${nsEngineSuffix()}`;
  } else if (flagged > 0) {
    statusEl.textContent = 'AI Found';
    statusEl.className = 'sub-status danger';
    detailEl.textContent = `${flagged} of ${found || scanned} passage${(found || scanned) === 1 ? '' : 's'} flagged as AI${nsEngineSuffix()}`;
  } else if (scanned > 0 || found > 0) {
    statusEl.textContent = 'Clean';
    statusEl.className = 'sub-status safe';
    const n = found || scanned;
    detailEl.textContent = `${n} passage${n === 1 ? '' : 's'} scanned — no AI text${nsEngineSuffix()}`;
  } else {
    statusEl.textContent = 'Active';
    statusEl.className = 'sub-status safe';
    detailEl.textContent = `Scanning this page${nsEngineSuffix()}…`;
  }
}

function nsFetchEngineStatus() {
  try {
    chrome.runtime.sendMessage({ type: 'getEngineStatus' }, (resp) => {
      if (chrome.runtime.lastError || !resp) return;
      _nsEngineStatus = resp;
      nsRenderOnPageRow();
      // NOTE: we don't auto-warm from the popup — the model downloads lazily
      // on the first real page scan. The popup just reflects whatever state the
      // engine is in (idle / downloading / ready).
      // Keep polling while the engine is still warming up (loading or idle),
      // so the % advances and 'ready' lands without reopening the popup.
      const settling = resp.engine === 'local' && (resp.state === 'loading' || resp.state === 'idle');
      if (settling && !_nsEnginePoll) {
        _nsEnginePoll = setInterval(nsFetchEngineStatus, 1200);
      } else if (!settling && _nsEnginePoll) {
        clearInterval(_nsEnginePoll); _nsEnginePoll = null;
      }
    });
  } catch (_) {}
}

function nsWireToggle(buttonId, getOn, onToggle) {
  const btn = document.getElementById(buttonId);
  if (!btn) return;
  btn.addEventListener('click', async () => {
    const settings = await nsLoadSettings();
    const next = !getOn(settings);
    const patched = await onToggle(next);
    nsApplyToggleState(btn, getOn(patched));
  });
}

async function nsInitToggles() {
  const settings = await nsLoadSettings();

  // Initial UI state
  nsApplyToggleState(document.getElementById('overlay-toggle'),      settings.overlays.enabled !== false);
  nsApplyToggleState(document.getElementById('text-toggle'),         settings.detection.text   !== false);
  nsApplyToggleState(document.getElementById('image-toggle'),        settings.detection.image  !== false);
  nsApplyToggleState(document.getElementById('video-toggle'),        settings.detection.video  !== false);

  _nsTextEnabled = settings.detection.text !== false;
  nsRenderOnPageRow();
  // Pull the on-device engine status (download %, GPU/CPU) for the Text row.
  if (_nsTextEnabled) nsFetchEngineStatus();

  // Wire interactions
  nsWireToggle('overlay-toggle',
    s => s.overlays.enabled !== false,
    (next) => nsSaveSettings({ overlays: { enabled: next } })
  );
  nsWireToggle('text-toggle',
    s => s.detection.text !== false,
    (next) => { _nsTextEnabled = next; nsRenderOnPageRow(); if (next) nsFetchEngineStatus(); return nsSaveSettings({ detection: { text: next } }); }
  );
  nsWireToggle('image-toggle',
    s => s.detection.image !== false,
    (next) => nsSaveSettings({ detection: { image: next } })
  );
  nsWireToggle('video-toggle',
    s => s.detection.video !== false,
    (next) => nsSaveSettings({ detection: { video: next } })
  );

  // React to changes made elsewhere (options page, another popup tab)
  chrome.storage.onChanged.addListener((changes, area) => {
    if (area !== 'local' || !changes.nithicSettings) return;
    const next = changes.nithicSettings.newValue || NS_DEFAULTS;
    const ov  = { ...NS_DEFAULTS.overlays,  ...(next.overlays  || {}) };
    const det = { ...NS_DEFAULTS.detection, ...(next.detection || {}) };
    nsApplyToggleState(document.getElementById('overlay-toggle'),      ov.enabled       !== false);
    nsApplyToggleState(document.getElementById('text-toggle'),         det.text         !== false);
    nsApplyToggleState(document.getElementById('image-toggle'),        det.image        !== false);
    nsApplyToggleState(document.getElementById('video-toggle'),        det.video        !== false);
    const wasEnabled = _nsTextEnabled;
    _nsTextEnabled = det.text !== false;
    nsRenderOnPageRow();
    if (_nsTextEnabled && !wasEnabled) nsFetchEngineStatus();
  });
}

if (document.readyState === 'loading') {
  document.addEventListener('DOMContentLoaded', nsInitToggles);
} else {
  nsInitToggles();
}
