(() => {
  if (window.__lsYellowPagesOverlay) return;
  window.__lsYellowPagesOverlay = true;

  const STYLE_ID = 'ls-yp-scrape-styles';
  const CONTAINER_ID = 'ls-yp-scrape-container';
  const STATUS_ID = 'ls-yp-scrape-status';
  const SESSION_KEY = '__lsYellowPagesScrapeState';
  const DEMO_MAX_PAGES = 1;
  const DEMO_BLUR_AFTER_PAGES = 1;
  const DEMO_FIRST_PAGE_NOTE = 'Demo preview captures only the first Yellow Pages page. Upgrade to unlock unlimited pages and exports.';

  const styles = `
    #${CONTAINER_ID}{z-index:2147483647;font-family:"Inter","Segoe UI",sans-serif;display:flex;gap:8px;position:fixed;top:18px;right:20px;pointer-events:none;flex-direction:column;align-items:flex-end;}
    #${CONTAINER_ID} button{pointer-events:auto;background:linear-gradient(135deg,rgba(34,211,238,.92),rgba(56,189,248,.92));color:#021524;border:none;border-radius:999px;padding:10px 18px;font-weight:600;font-size:14px;cursor:pointer;box-shadow:0 14px 32px rgba(34,211,238,.28);display:inline-flex;align-items:center;gap:8px;transition:transform .18s ease,box-shadow .18s ease;}
    #${CONTAINER_ID} button:hover{transform:translateY(-2px);box-shadow:0 18px 38px rgba(34,211,238,.34);}
    #${CONTAINER_ID} button:disabled{opacity:.55;cursor:not-allowed;box-shadow:none;transform:none;}
    #${STATUS_ID}{pointer-events:auto;padding:6px 10px;border-radius:8px;background:rgba(15,23,42,.85);color:rgba(226,232,240,.88);font-size:12px;box-shadow:0 10px 24px rgba(15,23,42,.4);max-width:260px;text-align:right;transition:color .15s ease;}
    #${STATUS_ID}.error{color:#f87171;}
    @media(max-width:640px){#${CONTAINER_ID}{top:auto;bottom:18px;right:16px;}}
  `;

  const injectStyles = () => {
    if (document.getElementById(STYLE_ID)) return;
    const styleEl = document.createElement('style');
    styleEl.id = STYLE_ID;
    styleEl.textContent = styles;
    (document.head || document.documentElement).appendChild(styleEl);
  };

  const container = document.createElement('div');
  container.id = CONTAINER_ID;
  const button = document.createElement('button');
  button.type = 'button';
  button.textContent = 'Start Scraping';
  const status = document.createElement('div');
  status.id = STATUS_ID;
  const defaultStatus = 'Ready – run a Yellow Pages search, then click the button.';
  status.textContent = defaultStatus;
  container.appendChild(button);
  container.appendChild(status);

  const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
  const cleanText = (value) => (typeof value === 'string' ? value.replace(/\s+/g, ' ').trim() : '');

  const toAbsoluteUrl = (href) => {
    if (!href) return '';
    try {
      return new URL(href, location.origin).toString();
    } catch (error) {
      return href;
    }
  };

  const normalizeListUrl = (url) => {
    if (!url) return '';
    try {
      const parsed = new URL(url, location.origin);
      parsed.hash = '';
      const entries = Array.from(parsed.searchParams.entries()).sort(([aKey], [bKey]) => aKey.localeCompare(bKey));
      parsed.search = '';
      entries.forEach(([key, value]) => parsed.searchParams.append(key, value));
      const serialized = parsed.searchParams.toString();
      parsed.search = serialized ? `?${serialized}` : '';
      return parsed.toString();
    } catch (_) {
      return url;
    }
  };

  const normalizeProfileUrl = (url) => {
    if (!url) return '';
    try {
      const parsed = new URL(url, location.origin);
      parsed.hash = '';
      parsed.search = parsed.searchParams.toString() ? `?${parsed.searchParams.toString()}` : '';
      return parsed.toString();
    } catch (_) {
      return url;
    }
  };

  const parseShowingCount = () => {
    const text = cleanText(document.querySelector('.showing-count')?.textContent || '');
    const match = text.match(/Showing\s+(\d+)\s*-\s*(\d+)\s+of\s+([\d,]+)/i);
    if (!match) {
      return { start: 0, end: 0, total: 0 };
    }
    const start = Number(match[1]);
    const end = Number(match[2]);
    const total = Number(match[3].replace(/,/g, ''));
    return {
      start: Number.isNaN(start) ? 0 : start,
      end: Number.isNaN(end) ? 0 : end,
      total: Number.isNaN(total) ? 0 : total
    };
  };

  const isSponsoredCard = (card) => {
    if (!card || typeof card.querySelector !== 'function') return false;
    if (card.classList && (card.classList.contains('result-sponsored') || card.classList.contains('listing-sponsored'))) return true;
    if (card.hasAttribute('data-yp-sponsored')) return true;
    if (card.querySelector('.ad-pill, .sponsored-label, .result-sponsored-label, .ad-badge')) return true;
    const sponsorText = cleanText(card.querySelector('.sponsored-label, .ad-pill, .ad-badge')?.textContent || '');
    return /sponsored/i.test(sponsorText);
  };

  const extractListingFromCard = (card) => {
    if (!card || isSponsoredCard(card)) return null;
    const nameAnchor = card.querySelector('a.business-name');
    const name = cleanText(nameAnchor?.textContent || '');
    if (!name) return null;
    const profileUrl = nameAnchor ? toAbsoluteUrl(nameAnchor.getAttribute('href')) : '';
    const canonical = profileUrl ? normalizeProfileUrl(profileUrl) : '';
    const ratingRaw = cleanText(card.querySelector('.ratings .count, .result-rating .count, .rating .count')?.textContent || '');
    const rating = ratingRaw.replace(/[()]/g, '').trim();
    const reviewsRaw = cleanText(card.querySelector('.ratings .ta-count, .rating .review-count, .ta-count, .count.review-count')?.textContent || '');
    const reviews = reviewsRaw.replace(/[()]/g, '').trim();
    const phone = cleanText(card.querySelector('.phones.phone.primary')?.textContent || '');
    const street = cleanText(card.querySelector('.adr .street-address')?.textContent || '');
    const locality = cleanText(card.querySelector('.adr .locality')?.textContent || '');
    const address = [street, locality].filter(Boolean).join(', ');
    const statusLabel = cleanText(card.querySelector('.open-status')?.textContent || '');
    const websiteAnchor = card.querySelector('a.track-visit-website');
    const websiteUrl = websiteAnchor ? toAbsoluteUrl(websiteAnchor.getAttribute('href')) : '';
    const websiteLabel = cleanText(websiteAnchor?.textContent || '') || websiteUrl;
    return {
      source: 'yellowpages',
      name,
      rating,
      reviews,
      hours: statusLabel,
      phone,
      websiteUrl,
      websiteLabel,
      address,
      profileUrl,
      canonical
    };
  };

  const loadState = () => {
    try {
      const raw = sessionStorage.getItem(SESSION_KEY);
      return raw ? JSON.parse(raw) : null;
    } catch (error) {
      console.warn('[LS][YellowPages] Failed to load session state', error);
      return null;
    }
  };

  const saveState = (state) => {
    if (!state) return;
    try {
      sessionStorage.setItem(SESSION_KEY, JSON.stringify(state));
    } catch (error) {
      console.warn('[LS][YellowPages] Failed to save session state', error);
    }
  };

  const clearState = () => {
    try {
      sessionStorage.removeItem(SESSION_KEY);
    } catch (error) {
      console.warn('[LS][YellowPages] Failed to clear session state', error);
    }
  };

  const setStatus = (message, opts = {}) => {
    status.textContent = message || defaultStatus;
    if (opts.error) {
      status.classList.add('error');
    } else {
      status.classList.remove('error');
    }
  };

  const setBusy = (busy) => {
    if (busy) {
      button.disabled = true;
      button.textContent = 'Scraping…';
    } else {
      button.disabled = false;
      button.textContent = 'Start Scraping';
    }
  };

  const isProfilePage = () => /\/mip\//i.test(location.pathname) || /\/mip\//i.test(location.href);
  const isSearchPage = () => /\/search/i.test(location.pathname) || document.querySelector('.srp-listing');

  const updateVisibility = () => {
    const onSearch = isSearchPage() && !isProfilePage();
    container.style.display = onSearch ? 'flex' : 'none';
  };

  const attachUi = () => {
    if (!document.body) return;
    injectStyles();
    if (!document.body.contains(container)) {
      document.body.appendChild(container);
    }
    updateVisibility();
  };

  const sendRuntimeMessage = (payload) => {
    if (!payload || !chrome?.runtime?.sendMessage) return;
    try {
      chrome.runtime.sendMessage(payload);
    } catch (error) {
      console.warn('[LS][YellowPages] runtime message failed', error);
    }
  };

  const requestBackgroundTabClose = () => {
    const fallbackClose = () => {
      try { window.close(); } catch (_) {}
    };
    if (!chrome?.runtime?.sendMessage) {
      fallbackClose();
      return;
    }
    try {
      chrome.runtime.sendMessage({ type: 'yellowpages-close-tab' });
      setTimeout(fallbackClose, 600);
    } catch (error) {
      console.warn('[LS][YellowPages] close tab message threw', error);
      fallbackClose();
    }
  };

  const createState = () => ({
    runId: `yp-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
    mode: 'running',
    listUrl: location.href,
    results: [],
    seen: {},
    visitedPages: [],
    pendingUrl: null,
    totalExpected: parseShowingCount().total || 0,
    startNotified: false,
    updatedAt: Date.now(),
    demoBlurFrom: null
  });

  const ensureStartEvent = (state) => {
    if (!state || state.startNotified) return;
    sendRuntimeMessage({
      type: 'yellowpages-scrape-start',
      url: state.listUrl || location.href,
      runId: state.runId,
      expected: state.totalExpected || 0
    });
    state.startNotified = true;
    saveState(state);
  };

  const reportProgress = (state, record) => {
    if (!state) return;
    const snapshot = Array.isArray(state.results) ? state.results.map((item) => ({ ...item })) : [];
    sendRuntimeMessage({
      type: 'yellowpages-scrape-progress',
      item: record,
      items: snapshot,
      count: snapshot.length,
      index: snapshot.length,
      total: state.totalExpected || snapshot.length,
      url: state.listUrl || location.href,
      runId: state.runId,
      demoBlurFrom: state.demoBlurFrom || null
    });
    setStatus(`Captured ${snapshot.length} businesses…`);
  };

  const reportError = (state, message) => {
    setStatus(message || 'Scrape failed.', { error: true });
    setBusy(false);
    sendRuntimeMessage({
      type: 'yellowpages-scrape-error',
      error: message || 'Scrape failed.',
      url: state?.listUrl || location.href,
      runId: state?.runId || null
    });
    clearState();
  };

  const finalizeScrape = (state, options = {}) => {
    if (!state) return;
    state.mode = 'done';
    const snapshot = Array.isArray(state.results) ? state.results.map((item) => ({ ...item })) : [];
    sendRuntimeMessage({
      type: 'yellowpages-scrape-results',
      items: snapshot,
      count: snapshot.length,
      url: state.listUrl || location.href,
      runId: state.runId,
      note: options.note || null,
      demoBlurFrom: state.demoBlurFrom || null
    });
    setStatus(options.note || `Captured ${snapshot.length} businesses.`);
    setBusy(false);
    clearState();
    requestBackgroundTabClose();
  };

  const waitForListings = async (timeoutMs = 15000) => {
    const start = Date.now();
    while (Date.now() - start < timeoutMs) {
      const listings = document.querySelectorAll('.srp-listing');
      if (listings.length) return Array.from(listings);
      await sleep(150);
    }
    return Array.from(document.querySelectorAll('.srp-listing'));
  };

  const appendListingsFromCards = (state, cards) => {
    if (!state || !Array.isArray(cards)) return [];
    if (!state.results) state.results = [];
    if (!state.seen || typeof state.seen !== 'object') state.seen = {};
    const additions = [];
    cards.forEach((card) => {
      const record = extractListingFromCard(card);
      if (!record) return;
      const key = record.canonical || record.profileUrl || `${record.name}|${record.phone}|${record.address}`;
      if (!key || state.seen[key]) return;
      state.seen[key] = true;
      state.results.push(record);
      additions.push(record);
      reportProgress(state, record);
    });
    return additions;
  };

  const markPageVisited = (state, url) => {
    if (!state || !url) return;
    if (!Array.isArray(state.visitedPages)) state.visitedPages = [];
    if (!state.visitedPages.includes(url)) {
      state.visitedPages.push(url);
    }
  };

  const hasVisitedPage = (state, url) => {
    if (!state || !url) return false;
    if (!Array.isArray(state.visitedPages)) return false;
    return state.visitedPages.includes(url);
  };

  const findNextPageUrl = () => {
    const link = document.querySelector('a.next.ajax-page:not(.disabled), a.next:not(.disabled)');
    if (!link) return '';
    if (link.classList && link.classList.contains('disabled')) return '';
    if (link.getAttribute('aria-disabled') === 'true') return '';
    const href = link.getAttribute('href') || link.href;
    if (!href) return '';
    return toAbsoluteUrl(href);
  };

  const processCurrentPage = async (state) => {
    if (!state) return;
    if (!isSearchPage()) {
      setStatus('Open a Yellow Pages results list to continue.', { error: true });
      setBusy(false);
      return;
    }
    setBusy(true);
    state.mode = 'running';
    state.listUrl = state.listUrl || location.href;
    const currentUrl = normalizeListUrl(location.href);
    if (state.pendingUrl && currentUrl === normalizeListUrl(state.pendingUrl)) {
      state.pendingUrl = null;
    }
    saveState(state);

    setStatus('Scanning Yellow Pages results…');
    const cards = await waitForListings();
    if (!cards.length) {
      reportError(state, 'No listings were detected on this page. Scroll and try again.');
      return;
    }

    ensureStartEvent(state);
    appendListingsFromCards(state, cards);
    const showing = parseShowingCount();
    if (showing.total && (!state.totalExpected || showing.total > state.totalExpected)) {
      state.totalExpected = showing.total;
    }
    markPageVisited(state, currentUrl);
    const visitedCount = Array.isArray(state.visitedPages) ? state.visitedPages.length : 0;
    if (!state.demoBlurFrom && visitedCount === DEMO_BLUR_AFTER_PAGES) {
      state.demoBlurFrom = state.results.length + 1;
    }
    state.updatedAt = Date.now();
    saveState(state);

    const nextUrl = findNextPageUrl();
    const limitReached = visitedCount >= DEMO_MAX_PAGES;
    if (!limitReached && nextUrl && !hasVisitedPage(state, normalizeListUrl(nextUrl))) {
      state.pendingUrl = nextUrl;
      state.updatedAt = Date.now();
      saveState(state);
      setStatus('Loading next results page…');
      await sleep(450);
      try {
        location.assign(nextUrl);
      } catch (_) {
        location.href = nextUrl;
      }
      return;
    }

    if (limitReached) {
      finalizeScrape(state, { note: DEMO_FIRST_PAGE_NOTE });
      return;
    }

    finalizeScrape(state);
  };

  const resumeIfNeeded = () => {
    const state = loadState();
    if (state && state.mode === 'running') {
      setStatus('Resuming previous scrape…');
      setBusy(true);
      processCurrentPage(state);
    }
  };

  button.addEventListener('click', () => {
    const existing = loadState();
    if (existing && existing.mode === 'running') {
      setStatus('Resuming ongoing scrape…');
      setBusy(true);
      processCurrentPage(existing);
      return;
    }
    if (!isSearchPage()) {
      setStatus('Open a Yellow Pages search results page first.', { error: true });
      return;
    }
    const state = createState();
    saveState(state);
    processCurrentPage(state);
  });

  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', attachUi, { once: true });
  } else {
    attachUi();
  }

  const hrefWatcher = () => {
    updateVisibility();
  };
  setInterval(hrefWatcher, 800);
  watchDom();
  resumeIfNeeded();

  function watchDom() {
    const observer = new MutationObserver(() => updateVisibility());
    observer.observe(document.documentElement || document.body, { childList: true, subtree: true });
  }
})();
