// DOM-Structure Signal Providers (v3)
// Typed features for browser-in-browser (se-browser-in-browser-v3), fake-chrome
// (se-fake-chrome-v3) and clickjacking (se-clickjacking-v3). Ported from the
// dead detectors of the same names. They read a pre-computed DOM snapshot
// (target.dom) built by content.js collectDomStructure() — the content script is
// the only place with real DOM + computed-style access. Providers only score.
//
// Snapshot shape (target.dom):
//   {
//     iframes: [{ opacity, coverage, position, zIndex, pointerEvents, visibility, crossOrigin }],
//     bitbCandidates: [{ hasAddressBarText, fakeUrl, hasLoginForm, isCentered, hasBoxShadow, hasBorder, widthPercent }],
//     fakeChromeTop: [{ top, widthPercent, zIndex, hasUrlText, hasInput }],
//     isFramed: bool, isFullscreen: bool, vw, vh
//   }

/**
 * @param {import('../../core/signal-provider.js').SignalProviderRegistry} registry
 */
export function registerDomStructureSignals(registry) {
  // ── dom.clickjacking_overlay ──────────────────
  // A large, near-transparent, INTERACTIVE iframe/overlay covering the viewport.
  // Hard-gated (coverage > 0.5, opacity < 0.3, pointer-events on) so the tiny
  // invisible iframes legit SDKs use (reCAPTCHA badge, Stripe card fields) don't
  // trip it — those are small (low coverage) or fully opaque when shown.
  registry.register('dom', 'clickjacking_overlay', (target) => {
    const dom = target.dom || {};
    const frames = dom.iframes || [];
    for (const f of frames) {
      const op = typeof f.opacity === 'number' ? f.opacity : parseFloat(f.opacity);
      const interactive = f.pointerEvents !== 'none';
      if (!interactive) continue;
      // transparent full-viewport overlay
      if ((f.coverage || 0) > 0.5 && op >= 0 && op < 0.3) {
        return { value: true, metadata: { kind: 'transparent-iframe', opacity: op, coverage: f.coverage } };
      }
      // hidden but still interactive, and sizable
      if (f.visibility === 'hidden' && (f.coverage || 0) > 0.3) {
        return { value: true, metadata: { kind: 'hidden-interactive-iframe', coverage: f.coverage } };
      }
    }
    return { value: false };
  }, { returnType: 'boolean', scope: 'tab', description: 'Transparent/hidden full-viewport interactive overlay (clickjacking)' });

  // ── dom.bitb_window ───────────────────────────
  // Score a "fake browser window": a positioned, shadowed modal that shows a
  // URL-looking address bar and (ideally) a login form. The fake address bar is
  // the load-bearing signal — legit modals don't render a URL inside themselves.
  registry.register('dom', 'bitb_window', (target) => {
    const dom = target.dom || {};
    const cands = dom.bitbCandidates || [];
    let best = 0, meta = null;
    for (const c of cands) {
      let score = 0;
      if (c.hasAddressBarText) score += 3;
      if (c.hasLoginForm) score += 2;
      if (c.isCentered) score += 1;
      if (c.hasBoxShadow) score += 1;
      if (score > best) { best = score; meta = { fakeUrl: c.fakeUrl, hasLoginForm: c.hasLoginForm, score }; }
    }
    return { value: best, metadata: best > 0 ? meta : null };
  }, { returnType: 'number', scope: 'tab', description: 'Fake-browser-window suspicion score' });

  // ── dom.fake_browser_chrome ───────────────────
  // A fixed/absolute bar pinned to the top of the viewport that displays a URL
  // (text or an input whose value/placeholder is a URL) — a fake address bar.
  // Real top navbars don't render raw https:// URLs.
  registry.register('dom', 'fake_browser_chrome', (target) => {
    const dom = target.dom || {};
    const bars = dom.fakeChromeTop || [];
    for (const b of bars) {
      if (b.hasUrlText || b.hasInput) {
        return { value: true, metadata: { top: b.top, widthPercent: b.widthPercent } };
      }
    }
    return { value: false };
  }, { returnType: 'boolean', scope: 'tab', description: 'Fake browser chrome / address bar at top of viewport' });

  // ── dom.is_fullscreen ─────────────────────────
  registry.register('dom', 'is_fullscreen', (target) => {
    return { value: !!(target.dom && target.dom.isFullscreen) };
  }, { returnType: 'boolean', scope: 'tab', description: 'Document is in fullscreen mode' });
}
