from typing import List, Tuple
import requests
from bs4 import BeautifulSoup
from duckduckgo_search import DDGS
from googlesearch import search as google_search
import arxiv
import logging
from pydantic import ValidationError
import json
import wikipedia
import yfinance as yf
from ..tools.schemas import (
    FetchNewsParams,
    FetchArxivParams,
    FetchDDGParams,
    FetchTorrentsParams,
    FetchWikiParams,
    FetchIMDBParams,
    FetchYouTubeParams,
    FetchFinanceParams
)

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)


# ——— Utility: scrape a page for title + snippet ———
def scrape_page(url: str) -> Tuple[str, str]:
    try:
        global scrape_counter
        resp = requests.get(url, headers={"User-Agent": "Mozilla/5.0"}, timeout=5)
        resp.raise_for_status()
        soup = BeautifulSoup(resp.text, "html.parser")
        title = soup.title.string.strip() if soup.title else url
        paragraphs = soup.find_all("p")
        snippet = "\n".join(p.get_text().strip() for p in paragraphs)
        scrape_id = f"scrape_{scrape_counter}"
        scrape_counter += 1
        scraped_store[scrape_id] = {"href": url, "text": snippet}
        return title, snippet
    except Exception:
        return url, ""

# ——— Tool: Google N search ———
def fetch_news(**kwargs) -> List[str]:
    try:
        params = FetchNewsParams(**kwargs)
        results = []
        for url in google_search(params.query, num_results=params.max_results, unique=True):
            title, snippet = scrape_page(url)
            results.append(f"{title}\n{snippet}\n{url}")
            # logger.info("Google: %s", f"{title}\n{snippet}\n{url}")
            if len(results) >= params.max_results:
                break
        return results
    except ValidationError as e:
        logger.error(f"Invalid parameters: {e}")
        return []

# ——— Tool: arXiv search ———
def fetch_arxiv(**kwargs) -> List[str]:
    try:
        params = FetchArxivParams(**kwargs)
        papers = []
        search = arxiv.Search(query=params.query, max_results=params.max_results)
        for r in search.results():
            summary = r.summary.replace("\n", " ").strip()
            papers.append(f"{r.title}\nAbstract: {summary}\nPDF: {r.pdf_url}")
        return papers
    except ValidationError as e:
        logger.error(f"Invalid parameters: {e}")
        return []

# ——— Tool: DuckDuckGo text search ———
def search_google(**kwargs) -> List[str]:
    try:
        return fetch_news(**kwargs)
    except ValidationError as e:
        logger.error(f"Invalid parameters: {e}")
        return []

# ——— Tool: Torrent search ———
def fetch_torrents(**kwargs) -> List[str]:
    try:
        params = FetchTorrentsParams(**kwargs)
        return search_google(query=f"""{params.query} proxy "torrent" """, max_results=params.max_results)
    except ValidationError as e:
        logger.error(f"Invalid parameters: {e}")
        return []


scraped_store = {}
scrape_counter = 0

def fetch_wikipedia(**kwargs) -> List[str]:
    try:
        params = FetchWikiParams(**kwargs)
        wikipedia.set_lang("en")
        results = []
        global scrape_counter
        for title in wikipedia.search(params.query, results=params.max_results):
            try:
                page = wikipedia.page(title, auto_suggest=False)
                scrape_id = f"scrape_{scrape_counter}"
                scrape_counter += 1
                scraped_store[scrape_id] = {"href": page.url, "text": page.summary}
                results.append(f"{page.title}\n{page.summary}\n{page.url}")
            except Exception as e:
                logger.warning(f"Wikipedia subpage error: {e}")
        return results
    except Exception as e:
        logger.error(f"Wikipedia fetch error: {e}")
        return []

def fetch_imdb(**kwargs) -> List[str]:
    try:
        params = FetchIMDBParams(**kwargs)
        return search_google(query=f"{params.query} site:imdb.com", max_results=params.max_results)
    except Exception as e:
        logger.error(f"IMDB fetch error: {e}")
        return []

def fetch_youtube(**kwargs) -> List[str]:
    try:
        params = FetchYouTubeParams(**kwargs)
        return search_google(query=f"{params.query} site:youtube.com", max_results=params.max_results)
    except Exception as e:
        logger.error(f"YouTube fetch error: {e}")
        return []

def fetch_finance(**kwargs) -> List[str]:
    try:
        params = FetchFinanceParams(**kwargs)
        results = []
        global scrape_counter
        tickers = params.query.strip().split()
        for symbol in tickers:
            ticker = yf.Ticker(symbol)
            info = ticker.info
            text = info.get("longBusinessSummary") or info.get("summary") or ""
            url = f"https://finance.yahoo.com/quote/{symbol}"
            scrape_id = f"scrape_{scrape_counter}"
            scrape_counter += 1
            scraped_store[scrape_id] = {"href": url, "text": text}
            results.append(f"{symbol.upper()}\n{text}\n{url}")
        return results
    except Exception as e:
        logger.error(f"Finance fetch error: {e}")
        return []
