// content/google-serp.js
// ════════════════════════════════════════════════════════════════════
// Browser-side Google SERP research — "VHunter via the browser".
// Runs on google.com/search and scrapes business/lead signals directly
// from the results page, so Hunter can discover prospects WITHOUT a Google
// Custom Search API key. Best-effort, defensive selectors (Google's DOM
// changes often) — it degrades gracefully rather than throwing.
//
// Public API (chrome.tabs.sendMessage from the background SW):
//   SCRAPE_GOOGLE_SERP  → { ok, query, organic:[{title,url,domain,snippet}],
//                           local:[{name,phone,address}], related:[...] }
// ════════════════════════════════════════════════════════════════════

const IL_PHONE_RE = /(?:\+972[-\s]?|0)(?:5\d|7\d|[2-4,8-9])[-\s]?\d{3}[-\s]?\d{4}/g;

function textOf(el) { return (el?.textContent || '').trim(); }

function domainOf(url) {
  try { return new URL(url).hostname.replace(/^www\./, ''); } catch { return ''; }
}

// Organic results — multiple selector strategies for resilience.
function scrapeOrganic() {
  const out = [];
  const seen = new Set();
  // Each organic result block historically lives under div.g / [data-hveid] with an <a><h3>.
  const blocks = document.querySelectorAll('div.g, div[data-hveid] , div.tF2Cxc, div.MjjYud');
  for (const b of blocks) {
    const a = b.querySelector('a[href^="http"]');
    const h3 = b.querySelector('h3');
    if (!a || !h3) continue;
    const url = a.href;
    const domain = domainOf(url);
    if (!domain || domain.includes('google.') || seen.has(domain)) continue;
    seen.add(domain);
    // Snippet: nearby description block
    const snip = b.querySelector('[data-sncf], .VwiC3b, .yXK7lf, span.aCOpRe') || b.querySelector('div > span');
    out.push({
      title: textOf(h3).slice(0, 200),
      url,
      domain,
      snippet: textOf(snip).slice(0, 300),
    });
    if (out.length >= 30) break;
  }
  return out;
}

// Local business pack (the "map" results with name/phone/address).
function scrapeLocal() {
  const out = [];
  // Local pack cards carry role=article or are inside [data-rc_ludocids] / .VkpGBb
  const cards = document.querySelectorAll('[data-rc_ludocids], .VkpGBb, div[jsname][role="article"]');
  for (const c of cards) {
    const txt = textOf(c);
    if (!txt) continue;
    const nameEl = c.querySelector('[role="heading"], .dbg0pd, .qBF1Pd, span.OSrXXb');
    const phones = (txt.match(IL_PHONE_RE) || []);
    const name = textOf(nameEl).slice(0, 120) || txt.split('\n')[0].slice(0, 120);
    if (!name) continue;
    out.push({
      name,
      phone: phones[0] || null,
      raw: txt.slice(0, 200),
    });
    if (out.length >= 20) break;
  }
  return out;
}

// "People also search for" / related queries — useful for SERP topic research.
function scrapeRelated() {
  const out = [];
  document.querySelectorAll('a, div').forEach((el) => {
    if (out.length >= 12) return;
    const t = textOf(el);
    // related-search chips are short and live in known containers
    if (t && t.length > 2 && t.length < 60 && el.closest('[data-abe], .y6Uyqe, .s75CSd, .b2Rnsc')) {
      if (!out.includes(t)) out.push(t);
    }
  });
  return out;
}

function scrapeSerp() {
  try {
    const q = new URLSearchParams(location.search).get('q') || '';
    return {
      ok: true,
      query: q,
      url: location.href,
      organic: scrapeOrganic(),
      local: scrapeLocal(),
      related: scrapeRelated(),
    };
  } catch (e) {
    return { ok: false, error: String(e?.message || e) };
  }
}

chrome.runtime.onMessage.addListener((msg, _sender, sendResponse) => {
  try {
    if (msg.type === 'SCRAPE_GOOGLE_SERP') { sendResponse(scrapeSerp()); return true; }
  } catch (e) { sendResponse({ ok: false, error: String(e?.message || e) }); }
  return false;
});

console.log('[organicai-serp] loaded on', location.host);
