from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.keys import Keys
from webdriver_manager.chrome import ChromeDriverManager
from urllib.parse import urlencode
import time
import math
import logging

from .extractor import extract_place_data

SCROLL_PAUSE_TIME = 2
MAX_SCROLL_ATTEMPTS_WITHOUT_NEW_LINKS = 5
BASE_URL = "https://www.google.com/maps/search/"

########################################################################################################

def calculate_bandwidth_usage(driver):
    total_bytes_sent = 0
    total_bytes_received = 0

    for request in driver.requests:
        if request.response:
            total_bytes_sent += len(str(request.headers).encode('utf-8'))
            total_bytes_received += int(request.response.headers.get('Content-Length', '0'))

    total_sent_mb = round(total_bytes_sent / (1024 * 1024), 4)
    total_received_mb = round(total_bytes_received / (1024 * 1024), 4)
    total_mb = round(total_sent_mb + total_received_mb, 4)

    print(f"🔄 Bandwidth usage:")
    print(f"   ⬆️ Sent: {total_sent_mb} MB")
    print(f"   ⬇️ Received: {total_received_mb} MB")
    print(f"   📊 Total: {total_mb} MB")

    return {
        "sent_mb": total_sent_mb,
        "received_mb": total_received_mb,
        "total_mb": total_mb
    }

########################################################################################################

def create_search_url(query, lang="en", geo_coordinates=None, zoom=12):
    params = {'hl': lang}
    encoded_query = query.replace(' ', '+')
    if geo_coordinates:
        lat, lng = geo_coordinates
        return f"{BASE_URL}{encoded_query}/@{lat},{lng},{zoom}z?{urlencode(params)}"
    return f"{BASE_URL}{encoded_query}?{urlencode(params)}"

########################################################################################################

def get_local_driver(headless=True):
    chrome_options = Options()
    if headless:
        chrome_options.add_argument("--headless=new")
        chrome_options.add_argument("--disable-gpu")

    chrome_options.add_argument("--blink-settings=imagesEnabled=false")
    chrome_options.add_argument("--disable-extensions")
    chrome_options.add_argument("--disable-popup-blocking")
    chrome_options.add_argument("--disable-dev-shm-usage")
    chrome_options.add_argument("--no-sandbox")
    chrome_options.add_argument("--disable-background-networking")
    chrome_options.add_argument(
        "user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
    )

    service = Service(ChromeDriverManager().install())
    return webdriver.Chrome(service=service, options=chrome_options)

########################################################################################################

def load_page_from_url(url: str, headless=True) -> dict:
    driver = get_local_driver(headless=headless)
    try:
        print(f"[SELENIUM] Visiting single URL: {url}")
        if hasattr(driver, "requests"):
            driver.requests.clear()

        driver.get(url)
        time.sleep(5)

        bandwidth_stats = calculate_bandwidth_usage(driver)
        html = driver.page_source

        return {
            "html": html,
            "bandwidth": bandwidth_stats
        }

    finally:
        driver.quit()

########################################################################################################

def scrape_google_maps(query: str, max_places: int = 5, lang: str = "en", headless: bool = True,
                        lat: float = None, lng: float = None, max_distance_km: float = 30.0):
    geo = (lat, lng) if lat and lng else None
    search_url = create_search_url(query, lang=lang, geo_coordinates=geo)

    driver = get_proxy_driver(headless=headless)
    try:
        logging.info(f"🔍 [SCRAPE-GET] Starting Google Maps scrape for query: '{query}'")
        if hasattr(driver, "requests"):
            driver.requests.clear()

        driver.get(search_url)
        time.sleep(5)

        scroll_attempts = 0
        links_seen = set()

        while True:
            elements = driver.find_elements(By.CSS_SELECTOR, "a.hfpxzc")
            new_links = set([e.get_attribute("href") for e in elements if e.get_attribute("href")])
            if new_links.issubset(links_seen):
                scroll_attempts += 1
            else:
                scroll_attempts = 0

            links_seen.update(new_links)

            if max_places and len(links_seen) >= max_places:
                break
            if scroll_attempts >= MAX_SCROLL_ATTEMPTS_WITHOUT_NEW_LINKS:
                break

            driver.find_element(By.TAG_NAME, "body").send_keys(Keys.END)
            time.sleep(SCROLL_PAUSE_TIME)

        place_urls = list(links_seen)[:max_places]
        results = []

        for url in place_urls:
            logging.info(f"🌐 Scraping place URL: {url}")
            driver.get(url)
            time.sleep(4)
            html = driver.page_source
            extracted = extract_place_data(html, google_map_url=url)
            if extracted:
                results.append(extracted)

        logging.info(f"✅ Scraping completed. Extracted {len(results)} places.")
        return results

    finally:
        driver.quit()
