'use strict';

const YELP_HOME = 'https://www.yelp.com/';
const YELP_PATTERN = /^https?:\/\/([a-z0-9-]+\.)*yelp\.com(\/|$)/i;

const openYelpBtn = document.getElementById('openYelpBtn');
const startScrapingBtn = document.getElementById('startScrapingBtn');
const statusMessage = document.getElementById('statusMessage');

let startEnabled = false;
let scraping = false;
let activeScrapeTabId = null;
let verificationActive = false;

function setStatus(text, options = {}) {
  if (!statusMessage) return;
  statusMessage.textContent = text;
  statusMessage.classList.toggle('status-error', Boolean(options.error));
}

function refreshStartButton() {
  if (!startScrapingBtn) return;
  const disabled = !startEnabled || scraping || verificationActive;
  startScrapingBtn.disabled = disabled;
  startScrapingBtn.textContent = scraping ? 'Scraping…' : 'Start Scraping';
}

function isYelpUrl(url) {
  return typeof url === 'string' && YELP_PATTERN.test(url);
}

function queryTabs(queryInfo) {
  return new Promise((resolve, reject) => {
    if (!chrome?.tabs?.query) {
      resolve([]);
      return;
    }
    chrome.tabs.query(queryInfo, (tabs) => {
      const error = chrome.runtime.lastError;
      if (error) {
        reject(new Error(error.message));
        return;
      }
      resolve(Array.isArray(tabs) ? tabs : []);
    });
  });
}

function updateTab(tabId, updateProperties) {
  return new Promise((resolve, reject) => {
    if (!chrome?.tabs?.update) {
      resolve(null);
      return;
    }
    chrome.tabs.update(tabId, updateProperties, (tab) => {
      const error = chrome.runtime.lastError;
      if (error) {
        reject(new Error(error.message));
        return;
      }
      resolve(tab);
    });
  });
}

function createTab(createProperties) {
  return new Promise((resolve, reject) => {
    if (!chrome?.tabs?.create) {
      const win = window.open(createProperties?.url || YELP_HOME, '_blank');
      if (win) {
        resolve(null);
      } else {
        reject(new Error('Browser blocked the new tab.'));
      }
      return;
    }
    chrome.tabs.create(createProperties, (tab) => {
      const error = chrome.runtime.lastError;
      if (error) {
        reject(new Error(error.message));
        return;
      }
      resolve(tab);
    });
  });
}

function tabsSendMessage(tabId, message) {
  return new Promise((resolve, reject) => {
    if (!chrome?.tabs?.sendMessage) {
      reject(new Error('Messaging unavailable.'));
      return;
    }
    chrome.tabs.sendMessage(tabId, message, (response) => {
      const error = chrome.runtime.lastError;
      if (error) {
        reject(new Error(error.message));
        return;
      }
      resolve(response);
    });
  });
}

function executeOverlay(tabId) {
  return new Promise((resolve, reject) => {
    if (!chrome?.scripting?.executeScript) {
      reject(new Error('Unable to inject scripts into Yelp tab.'));
      return;
    }
    chrome.scripting.executeScript(
      { target: { tabId }, files: ['js/yelp-overlay.js'] },
      () => {
        const error = chrome.runtime.lastError;
        if (error) {
          reject(new Error(error.message));
          return;
        }
        resolve();
      }
    );
  });
}

async function getActiveTab() {
  const tabs = await queryTabs({ active: true, currentWindow: true });
  return tabs[0] || null;
}

async function ensureOverlay(tabId) {
  try {
    await tabsSendMessage(tabId, { type: 'yelp-ensure-overlay' });
  } catch (error) {
    if (/Receiving end does not exist|No tab with id/i.test(error.message || '')) {
      await executeOverlay(tabId);
      await tabsSendMessage(tabId, { type: 'yelp-ensure-overlay' });
    } else {
      throw error;
    }
  }
}

async function openOrFocusYelpTab() {
  const activeTab = await getActiveTab();
  if (activeTab && isYelpUrl(activeTab.url || '')) {
    await updateTab(activeTab.id, { active: true });
    return activeTab.id;
  }

  const tabs = await queryTabs({ currentWindow: true });
  const existing = tabs.find((tab) => isYelpUrl(tab.url || ''));
  if (existing) {
    await updateTab(existing.id, { active: true });
    return existing.id;
  }

  const created = await createTab({ url: YELP_HOME, active: true });
  return created?.id ?? null;
}

async function updateActiveTabState() {
  try {
    const tab = await getActiveTab();
    startEnabled = Boolean(tab && isYelpUrl(tab.url || ''));
    if (verificationActive) {
      setStatus('Complete the Yelp verification challenge in the Yelp tab, then try again.', { error: true });
    } else if (startEnabled) {
      setStatus('Search on Yelp, then click Start Scraping to capture the visible results.');
    } else {
      setStatus('Open Yelp.com to begin. This tool only runs on Yelp tabs.');
    }
  } catch (error) {
    startEnabled = false;
    setStatus('Unable to read the active tab. Open Yelp.com to begin.', { error: true });
  } finally {
    refreshStartButton();
  }
}

async function handleOpenYelpClick() {
  try {
    const tabId = await openOrFocusYelpTab();
    if (tabId != null) {
      startEnabled = true;
      verificationActive = false;
    }
    await updateActiveTabState();
    window.close();
  } catch (error) {
    console.warn('[Popup] Failed to open Yelp tab', error);
    setStatus(error.message || 'Unable to open Yelp.com. Try again.', { error: true });
  }
}

async function handleStartScrapingClick() {
  try {
    const tab = await getActiveTab();
    if (!tab || !isYelpUrl(tab.url || '')) {
      startEnabled = false;
      refreshStartButton();
      setStatus('Switch to the Yelp results tab before starting the scraper.', { error: true });
      return;
    }
    if (verificationActive) {
      setStatus('Finish the Yelp verification first, then start scraping.', { error: true });
      return;
    }
    scraping = true;
    activeScrapeTabId = tab.id;
    refreshStartButton();
    setStatus('Preparing the Yelp results for scraping…');

    await ensureOverlay(tab.id);
    setStatus('Scraping visible Yelp results…');

    const response = await tabsSendMessage(tab.id, { type: 'yelp-trigger-scrape' });
    if (response && response.ok) {
      setStatus(response.message || 'Scrape complete.');
    } else if (response && response.message) {
      setStatus(response.message, { error: true });
    } else {
      setStatus('Scrape did not return any data. Make sure the results are visible.', { error: true });
    }
  } catch (error) {
    setStatus(error.message || 'Scrape failed. Reload the Yelp page and try again.', { error: true });
  } finally {
    scraping = false;
    refreshStartButton();
  }
}

function handleRuntimeMessage(message, sender) {
  if (!message || typeof message !== 'object') return;
  if (message.type === 'yelp-verification-required') {
    verificationActive = true;
    if (sender?.tab?.id != null) {
      activeScrapeTabId = sender.tab.id;
    }
    setStatus('Yelp is verifying your browser. Complete the challenge in the Yelp tab, then retry.', { error: true });
    scraping = false;
    refreshStartButton();
    return;
  }
  if (message.type === 'yelp-verification-cleared') {
    verificationActive = false;
    if (sender?.tab?.id != null) {
      activeScrapeTabId = sender.tab.id;
    }
    if (!scraping) {
      setStatus('Verification cleared. Search on Yelp and start scraping when ready.');
    }
    updateActiveTabState();
    return;
  }

  if (!sender || !sender.tab || sender.tab.id !== activeScrapeTabId) {
    return;
  }

  if (message.type === 'yelp-scrape-start') {
    scraping = true;
    setStatus('Yelp acknowledged the scrape request. Collecting visible businesses…');
    refreshStartButton();
  } else if (message.type === 'yelp-scrape-results') {
    const count = Array.isArray(message.items) ? message.items.length : 0;
    setStatus(`Captured ${count} businesses from Yelp.`);
    scraping = false;
    refreshStartButton();
  } else if (message.type === 'yelp-scrape-error') {
    setStatus(message.error || 'Scrape failed inside Yelp. Adjust the page and try again.', { error: true });
    scraping = false;
    refreshStartButton();
  }
}

function init() {
  if (openYelpBtn) openYelpBtn.addEventListener('click', handleOpenYelpClick);
  if (startScrapingBtn) startScrapingBtn.addEventListener('click', handleStartScrapingClick);
  if (chrome?.runtime?.onMessage) {
    chrome.runtime.onMessage.addListener(handleRuntimeMessage);
  }
  updateActiveTabState();
}

init();
