// ═══════════════════════════════════════════════════════════════════
// Deep Iframe Inspector for Antigravity
// ═══════════════════════════════════════════════════════════════════
// Usage: Paste this entire script into the AG Renderer DevTools console
//        (Ctrl+Shift+I → Console tab in the main workbench window)
//
// This script recursively inspects ALL iframes, webview elements,
// and shadow DOMs to map the complete DOM tree including:
//   - iframe nesting depth and origin info
//   - webview elements and their executeJavaScript availability
//   - shadow DOM roots
//   - button inventory at each level
//   - Content Security Policy headers
//   - Cross-origin accessibility status
// ═══════════════════════════════════════════════════════════════════

(function deepIframeInspector() {
  'use strict';

  const SEP = '─'.repeat(70);
  const results = [];
  let nodeCount = 0;

  function log(msg) {
    console.log('[DEEP-INSPECT] ' + msg);
    results.push(msg);
  }

  function indent(depth) {
    return '  '.repeat(depth);
  }

  // ── Inspect a single document context ──
  function inspectDocument(doc, depth, label) {
    nodeCount++;
    const id = `node_${nodeCount}`;
    const pfx = indent(depth);

    log(`${pfx}┌─ ${label} (depth=${depth})`);

    if (!doc) {
      log(`${pfx}│  ⛔ document is null/undefined`);
      log(`${pfx}└─ END ${label}`);
      return;
    }

    // Basic doc info
    try {
      log(`${pfx}│  URL: ${(doc.URL || doc.documentURI || 'unknown').substring(0, 120)}`);
      log(`${pfx}│  title: "${(doc.title || '').substring(0, 80)}"`);
      log(`${pfx}│  readyState: ${doc.readyState}`);
      log(`${pfx}│  domain: ${doc.domain || 'N/A'}`);
    } catch (e) {
      log(`${pfx}│  ⛔ Cannot read doc properties: ${e.message}`);
    }

    // CSP meta tags
    try {
      const cspMetas = doc.querySelectorAll('meta[http-equiv="Content-Security-Policy"]');
      if (cspMetas.length > 0) {
        for (let i = 0; i < cspMetas.length; i++) {
          log(`${pfx}│  CSP[${i}]: ${(cspMetas[i].content || '').substring(0, 150)}`);
        }
      }
    } catch (e) {}

    // Count key elements
    try {
      const allEls = doc.querySelectorAll('*');
      const buttons = doc.querySelectorAll('button');
      const inputs = doc.querySelectorAll('input[type="button"],input[type="submit"]');
      const anchors = doc.querySelectorAll('a[role="button"]');
      const iframes = doc.querySelectorAll('iframe');
      const webviews = doc.querySelectorAll('webview');
      const divWithRole = doc.querySelectorAll('[role="button"]');

      log(`${pfx}│  Elements: total=${allEls.length} buttons=${buttons.length} roleBtn=${divWithRole.length} iframes=${iframes.length} webviews=${webviews.length}`);

      // Dump ALL buttons (not just first 10)
      if (buttons.length > 0) {
        log(`${pfx}│  ── Buttons ──`);
        const maxShow = Math.min(30, buttons.length);
        for (let i = 0; i < maxShow; i++) {
          const b = buttons[i];
          const txt = (b.textContent || '').trim().substring(0, 60);
          const cls = (b.className || '').substring(0, 50);
          const disabled = b.disabled ? ' [DISABLED]' : '';
          const hidden = (b.hidden || !b.offsetParent) ? ' [HIDDEN]' : '';
          const ariaLabel = b.getAttribute('aria-label') || '';
          const title = b.getAttribute('title') || '';
          log(`${pfx}│    btn[${i}]: "${txt}"${disabled}${hidden} class="${cls}" aria="${ariaLabel}" title="${title}"`);
        }
        if (buttons.length > maxShow) {
          log(`${pfx}│    ... +${buttons.length - maxShow} more buttons`);
        }
      }

      // Dump role="button" elements that aren't actual buttons
      if (divWithRole.length > 0) {
        log(`${pfx}│  ── role="button" elements ──`);
        const maxShow = Math.min(15, divWithRole.length);
        for (let i = 0; i < maxShow; i++) {
          const el = divWithRole[i];
          if (el.tagName === 'BUTTON') continue; // skip actual buttons
          const txt = (el.textContent || '').trim().substring(0, 60);
          const tag = el.tagName.toLowerCase();
          log(`${pfx}│    roleBtn[${i}]: <${tag}> "${txt}"`);
        }
      }

      // Recurse into shadow DOMs
      let shadowCount = 0;
      for (let i = 0; i < allEls.length; i++) {
        const sr = allEls[i].shadowRoot;
        if (sr) {
          shadowCount++;
          const tag = allEls[i].tagName.toLowerCase();
          const cls = (allEls[i].className || '').substring(0, 40);
          inspectDocument(sr, depth + 1, `ShadowRoot of <${tag} class="${cls}">`);
        }
      }
      if (shadowCount === 0) {
        log(`${pfx}│  (no shadow DOMs found)`);
      }

      // Recurse into iframes
      for (let i = 0; i < iframes.length; i++) {
        const f = iframes[i];
        const src = (f.src || '').substring(0, 120);
        const cls = (f.className || '').substring(0, 50);
        const id = f.id || '';
        const sandbox = f.getAttribute('sandbox') || 'none';
        const allow = f.getAttribute('allow') || '';

        let fLabel = `<iframe#${i}> id="${id}" class="${cls}" src="${src}" sandbox="${sandbox}"`;

        try {
          const idoc = f.contentDocument || (f.contentWindow && f.contentWindow.document);
          if (idoc) {
            inspectDocument(idoc, depth + 1, fLabel + ' [ACCESSIBLE]');
          } else {
            log(`${pfx}│  ${fLabel} → contentDocument=null`);
            // Try contentWindow info
            try {
              const cw = f.contentWindow;
              log(`${pfx}│    contentWindow exists: ${!!cw}`);
              if (cw) {
                log(`${pfx}│    contentWindow.length (sub-frames): ${cw.length}`);
                try { log(`${pfx}│    contentWindow.location: ${cw.location.href}`); } catch (e2) {
                  log(`${pfx}│    contentWindow.location: ⛔ ${e2.message.substring(0, 60)}`);
                }
              }
            } catch (e2) {}
          }
        } catch (e) {
          log(`${pfx}│  ${fLabel} → ⛔ BLOCKED: ${e.message.substring(0, 80)}`);
          // Still try to get some info about the blocked iframe
          try {
            const cw = f.contentWindow;
            log(`${pfx}│    contentWindow exists: ${!!cw}`);
            if (cw) {
              log(`${pfx}│    contentWindow.length (sub-frames): ${cw.length}`);
            }
          } catch (e2) {
            log(`${pfx}│    contentWindow also blocked: ${e2.message.substring(0, 60)}`);
          }
        }
      }

      // Recurse into webview elements
      for (let i = 0; i < webviews.length; i++) {
        const wv = webviews[i];
        const src = (wv.src || '').substring(0, 120);
        const cls = (wv.className || '').substring(0, 50);
        const partition = wv.getAttribute('partition') || '';
        const preload = wv.getAttribute('preload') || '';
        const nodeInteg = wv.getAttribute('nodeintegration') || '';
        const nodeIntegSub = wv.getAttribute('nodeintegrationinsubframes') || '';
        const webpref = wv.getAttribute('webpreferences') || '';

        log(`${pfx}│  ── <webview#${i}> ──`);
        log(`${pfx}│    src: ${src}`);
        log(`${pfx}│    class: ${cls}`);
        log(`${pfx}│    partition: ${partition}`);
        log(`${pfx}│    preload: ${preload}`);
        log(`${pfx}│    nodeintegration: ${nodeInteg}`);
        log(`${pfx}│    webpreferences: ${webpref}`);

        // Try contentDocument
        try {
          const wdoc = wv.contentDocument;
          if (wdoc) {
            inspectDocument(wdoc, depth + 1, `<webview#${i}> contentDocument [ACCESSIBLE]`);
          } else {
            log(`${pfx}│    contentDocument: null`);
          }
        } catch (e) {
          log(`${pfx}│    contentDocument: ⛔ ${e.message.substring(0, 60)}`);
        }

        // Check executeJavaScript availability
        log(`${pfx}│    executeJavaScript: ${typeof wv.executeJavaScript}`);
        if (typeof wv.executeJavaScript === 'function') {
          log(`${pfx}│    🔑 executeJavaScript IS AVAILABLE — attempting probe...`);
          try {
            wv.executeJavaScript(`
              (function() {
                var btns = document.querySelectorAll('button');
                var allEls = document.querySelectorAll('*');
                var iframes = document.querySelectorAll('iframe');
                var webviews = document.querySelectorAll('webview');
                var btnTexts = [];
                for (var i = 0; i < btns.length; i++) {
                  var txt = (btns[i].textContent || '').trim();
                  var disabled = btns[i].disabled ? ' [DISABLED]' : '';
                  var hidden = (btns[i].hidden || !btns[i].offsetParent) ? ' [HIDDEN]' : '';
                  var cls = (btns[i].className || '').substring(0, 40);
                  btnTexts.push('"' + txt.substring(0, 50) + '"' + disabled + hidden + ' cls=' + cls);
                }
                // Also check for role=button
                var roleBtns = document.querySelectorAll('[role="button"]');
                var roleBtnTexts = [];
                for (var j = 0; j < roleBtns.length; j++) {
                  if (roleBtns[j].tagName !== 'BUTTON') {
                    roleBtnTexts.push('<' + roleBtns[j].tagName.toLowerCase() + '> "' + (roleBtns[j].textContent || '').trim().substring(0, 40) + '"');
                  }
                }

                // Check for shadow DOMs
                var shadowCount = 0;
                for (var k = 0; k < allEls.length; k++) {
                  if (allEls[k].shadowRoot) shadowCount++;
                }

                return JSON.stringify({
                  url: document.URL,
                  title: document.title,
                  totalElements: allEls.length,
                  buttons: btns.length,
                  buttonTexts: btnTexts.slice(0, 30),
                  roleBtns: roleBtnTexts.slice(0, 15),
                  iframes: iframes.length,
                  webviews: webviews.length,
                  shadowDOMs: shadowCount
                });
              })()
            `).then(function(result) {
              try {
                const data = JSON.parse(result);
                console.log('[DEEP-INSPECT] 📦 webview#' + i + ' INTERNAL PROBE:');
                console.log('[DEEP-INSPECT]   URL: ' + data.url);
                console.log('[DEEP-INSPECT]   title: ' + data.title);
                console.log('[DEEP-INSPECT]   Elements: total=' + data.totalElements + ' buttons=' + data.buttons + ' iframes=' + data.iframes + ' webviews=' + data.webviews + ' shadowDOMs=' + data.shadowDOMs);
                if (data.buttonTexts.length > 0) {
                  console.log('[DEEP-INSPECT]   ── Buttons inside webview ──');
                  data.buttonTexts.forEach(function(t, idx) {
                    console.log('[DEEP-INSPECT]     btn[' + idx + ']: ' + t);
                  });
                }
                if (data.roleBtns.length > 0) {
                  console.log('[DEEP-INSPECT]   ── role="button" inside webview ──');
                  data.roleBtns.forEach(function(t, idx) {
                    console.log('[DEEP-INSPECT]     roleBtn[' + idx + ']: ' + t);
                  });
                }
              } catch (e) {
                console.log('[DEEP-INSPECT]   raw result: ' + result);
              }
            }).catch(function(e) {
              console.log('[DEEP-INSPECT]   ⛔ executeJavaScript FAILED: ' + e.message);
            });
          } catch (e) {
            log(`${pfx}│    ⛔ executeJavaScript call threw: ${e.message}`);
          }
        }

        // Try getWebContentsId (Electron-specific)
        try {
          if (typeof wv.getWebContentsId === 'function') {
            log(`${pfx}│    webContentsId: ${wv.getWebContentsId()}`);
          }
        } catch (e) {}
      }

    } catch (e) {
      log(`${pfx}│  ⛔ Error during inspection: ${e.message}`);
    }

    log(`${pfx}└─ END ${label}`);
  }

  // ── Window hierarchy ──
  function inspectWindowHierarchy() {
    log(SEP);
    log('📐 Window Hierarchy');
    log(SEP);
    log(`window.location.href: ${window.location.href}`);
    log(`window.location.origin: ${window.location.origin}`);
    log(`window.location.protocol: ${window.location.protocol}`);
    log(`window.frames.length: ${window.frames.length}`);
    log(`window === window.top: ${window === window.top}`);
    log(`window === window.parent: ${window === window.parent}`);
    log(`navigator.userAgent: ${navigator.userAgent.substring(0, 120)}`);

    // Check if we're in Electron
    try {
      log(`process.type: ${typeof process !== 'undefined' ? process.type : 'N/A'}`);
      log(`process.versions.electron: ${typeof process !== 'undefined' && process.versions ? process.versions.electron : 'N/A'}`);
    } catch (e) {
      log(`process info: N/A (${e.message.substring(0, 40)})`);
    }

    // Check webFrame (Electron renderer API)
    try {
      if (typeof require === 'function') {
        const { webFrame } = require('electron');
        log(`webFrame available: ${!!webFrame}`);
        if (webFrame) {
          log(`webFrame.routingId: ${webFrame.routingId}`);
        }
      }
    } catch (e) {
      log(`electron.webFrame: N/A (${e.message.substring(0, 40)})`);
    }

    // Check webContents access via remote/electron
    try {
      if (typeof require === 'function') {
        const electron = require('electron');
        const ipcRenderer = electron.ipcRenderer;
        log(`ipcRenderer available: ${!!ipcRenderer}`);
      }
    } catch (e) {
      log(`electron.ipcRenderer: N/A (${e.message.substring(0, 40)})`);
    }
  }

  // ── Main ──
  log('');
  log('═'.repeat(70));
  log('  DEEP IFRAME INSPECTOR — Antigravity DOM Analysis');
  log('  Timestamp: ' + new Date().toISOString());
  log('═'.repeat(70));
  log('');

  inspectWindowHierarchy();

  log('');
  log(SEP);
  log('📄 Document Tree (recursive)');
  log(SEP);

  inspectDocument(document, 0, 'Main Document');

  log('');
  log(SEP);
  log(`✅ Inspection complete. ${nodeCount} document contexts inspected.`);
  log(SEP);

  // Summary
  log('');
  log('📋 SUMMARY:');
  log('  Copy all [DEEP-INSPECT] lines from this console');
  log('  Webview executeJavaScript probe results will appear AFTER this summary (async)');

  return results;
})();
