import re
import logging
import subprocess
from concurrent.futures import ThreadPoolExecutor
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from bs4 import BeautifulSoup
from rake_nltk import Rake
import pandas as pd
import time
import nltk
from tqdm import tqdm
from langdetect import detect, DetectorFactory
import psutil

# Ensure deterministic results from langdetect
DetectorFactory.seed = 0

# Download NLTK resources if not already downloaded
def download_nltk_resources():
    nltk.download('punkt')

# Configure logging to show debug information
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)

# Function to start ChromeDriver using subprocess
def start_chromedriver_service():
    service_path = 'C:/WebDriver/chromedriver.exe'  # Update this path if necessary
    return subprocess.Popen(
        [service_path, '--port=0'],
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE
    )

# Fetch text from Pinterest search results
def get_text_from_pinterest_search(query, max_pins=10, max_workers=2):
    logger.info("Starting Pinterest search...")
    options = Options()
    options.add_argument('--headless')
    options.add_argument('--disable-gpu')
    options.add_argument('--no-sandbox')
    options.add_argument('--disable-dev-shm-usage')
    options.add_argument('--log-level=3')  # Suppress console logs

    # Set desired capabilities to suppress logging
    caps = DesiredCapabilities.CHROME.copy()
    caps['goog:loggingPrefs'] = {'browser': 'OFF', 'driver': 'OFF'}
    for key, value in caps.items():
        options.set_capability(key, value)

    # Start ChromeDriver using subprocess
    service_process = start_chromedriver_service()
    service = Service('C:/WebDriver/chromedriver.exe')  # Dummy service to pass to WebDriver
    driver = webdriver.Chrome(service=service, options=options)

    url = f"https://www.pinterest.com/search/pins/?q={query}"
    driver.get(url)
    time.sleep(5)  # Add a short delay to allow the page to load
    
    pin_texts = []
    pin_links = set()
    
    # Scroll to load more pins
    scroll_pause_time = 2
    last_height = driver.execute_script("return document.body.scrollHeight")

    while len(pin_links) < max_pins:
        driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
        time.sleep(scroll_pause_time)
        
        soup = BeautifulSoup(driver.page_source, 'html.parser')
        
        for a_tag in soup.find_all('a', href=True):
            href = a_tag['href']
            if href.startswith('/pin/') and len(pin_links) < max_pins:
                pin_links.add(f"https://www.pinterest.com{href}")

        new_height = driver.execute_script("return document.body.scrollHeight")
        if new_height == last_height:
            break
        last_height = new_height

    logger.info(f"Total collected pins: {len(pin_links)}")  # Log total collected pins

    with ThreadPoolExecutor(max_workers=max_workers) as executor:
        list(tqdm(executor.map(fetch_pin_text, pin_links, [pin_texts] * len(pin_links)), total=len(pin_links), desc="Fetching Pins"))

    driver.quit()
    service_process.terminate()  # Terminate the ChromeDriver subprocess
    return pin_texts

# Fetch text content from a Pinterest pin
def fetch_pin_text(link, pin_texts):
    try:
        options = Options()
        options.add_argument('--headless')
        options.add_argument('--disable-gpu')
        options.add_argument('--no-sandbox')
        options.add_argument('--disable-dev-shm-usage')
        options.add_argument('--log-level=3')  # Suppress console logs

        # Set desired capabilities to suppress logging
        caps = DesiredCapabilities.CHROME.copy()
        caps['goog:loggingPrefs'] = {'browser': 'OFF', 'driver': 'OFF'}
        for key, value in caps.items():
            options.set_capability(key, value)

        # Start ChromeDriver using subprocess
        service_process = start_chromedriver_service()
        service = Service('C:/WebDriver/chromedriver.exe')  # Dummy service to pass to WebDriver
        driver = webdriver.Chrome(service=service, options=options)
        
        driver.get(link)
        time.sleep(3)
        soup = BeautifulSoup(driver.page_source, 'html.parser')
        post_content = soup.find('meta', {'name': 'description'})['content']
        if post_content:
            pin_texts.append(post_content)
    except Exception as e:
        logger.error(f"Error fetching pin content: {e}")
    finally:
        driver.quit()
        service_process.terminate()  # Terminate the ChromeDriver subprocess

# Extract keywords from text using Rake and filter out non-English phrases
def extract_keywords(texts):
    r = Rake()
    keywords = []
    for text in texts:
        r.extract_keywords_from_text(text)
        ranked_phrases = r.get_ranked_phrases_with_scores()
        for score, phrase in ranked_phrases:
            # Exclude phrases that contain only numeric characters and non-English phrases
            if not re.match(r'^[0-9\s]+$', phrase) and is_english(phrase):
                keywords.append((score, phrase))
    keywords.sort(reverse=True)  # Sort by score in descending order
    return keywords

# Check if a given text is in English
def is_english(text):
    try:
        return detect(text) == 'en'
    except:
        return False

# Save keywords to CSV file
def save_keywords_to_csv(keywords, filename):
    if keywords:
        df = pd.DataFrame(keywords, columns=['Score', 'Keyword'])
        df.drop_duplicates(subset=['Keyword'], inplace=True)  # Remove duplicates
        df['Keyword'] = df['Keyword'].apply(lambda x: re.sub(r'\W+', ' ', x))  # Remove special characters
        df = df[df['Keyword'].apply(lambda x: len(x.split()) > 1)]  # Filter out single words
        df['Score'] = df['Score'].astype(int)  # Convert score to integer
        df.to_csv(filename, index=False)
        logger.info(f"Keywords saved to {filename} successfully.")
    else:
        logger.warning("No keywords found to save.")

# Calculate and display average score
def calculate_and_display_average(numbers):
    total = sum(numbers)
    average = total / len(numbers)
    formatted_average = "{:.1f}".format(average)  # Format the average to one decimal place
    logger.info("The average is: %s", formatted_average)

# Function to get current CPU usage
def get_cpu_usage():
    return psutil.cpu_percent()

if __name__ == "__main__":
    download_nltk_resources()
    
    keyword = input("Enter a keyword to search on Pinterest: ").strip()

    # Adjust max_pins and max_workers as needed
    post_texts = get_text_from_pinterest_search(keyword, max_pins=50, max_workers=2)

    if post_texts:
        logger.info("Processing collected pins...")
        keywords = extract_keywords(post_texts)
        save_keywords_to_csv(keywords, "keywords.csv")  # Correct
