"""Curiosity Query Generator - transforms trending topics into questions using LLM.

Uses Groq Llama 3.3 70B to analyze headlines and extract the explainer opportunity
hidden behind each one. Replaces mechanical concept extraction with intelligent
question generation.
"""

import os
import re
import time
import requests
from typing import List, Dict, Any, Set, Tuple, Optional
from datetime import datetime, timezone

from dotenv import load_dotenv
from groq import Groq

from .base import TrendItem

load_dotenv()


class CuriosityQueryCollector:
    """Generates curiosity queries from trending topics via Groq LLM."""

    def __init__(self):
        self.name = "curiosity_query"
        self.errors: List[str] = []
        self.groq_client = Groq(api_key=os.getenv("GROQ_API_KEY"))
        self.headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
        }
        self.stats = {
            "items_sent_to_groq": 0,
            "questions_generated": 0,
            "skipped_by_llm": 0,
            "youtube_validated": 0,
            "groq_errors": 0,
        }

    def _dedupe_headlines(self, items: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
        """Remove near-duplicate headlines (same story from multiple outlets)."""
        seen_normalized = set()
        unique = []

        for item in items:
            headline = item.get("topic_name", "")
            # Normalize: lowercase, remove punctuation, take first 50 chars
            normalized = re.sub(r'[^\w\s]', '', headline.lower())[:50]

            if normalized not in seen_normalized:
                seen_normalized.add(normalized)
                unique.append(item)

        return unique

    def _batch_items(self, items: List[Dict[str, Any]], batch_size: int = 25) -> List[List[Dict[str, Any]]]:
        """Split items into batches for API calls."""
        batches = []
        for i in range(0, len(items), batch_size):
            batches.append(items[i:i + batch_size])
        return batches

    def _call_groq_for_questions(self, batch: List[Dict[str, Any]]) -> List[Tuple[str, str, str]]:
        """
        Call Groq LLM to generate questions from a batch of headlines/trends.

        Returns list of (original_headline, generated_question, source) tuples.
        """
        # Build the numbered list of items
        items_text = ""
        for i, item in enumerate(batch, 1):
            headline = item.get("topic_name", "")[:150]  # Limit length
            source = item.get("source", "unknown")
            items_text += f"{i}. [{source}] {headline}\n"

        prompt = f"""You are analyzing trending news headlines and search terms to identify what questions a curious but uninformed person would ask after seeing each one. Your goal is to find the EXPLAINER OPPORTUNITY hidden behind each headline.

For each item below, respond with either:
- A specific question that a regular person would want answered (phrased naturally, like how someone would type it into Google or ask on Reddit)
- "SKIP" if there's no natural explainer question (e.g., sports scores, celebrity gossip with no deeper angle, weather, stock prices, game results, athlete performances)

Rules:
- The question should be about understanding WHY or HOW something works, not just WHAT happened
- Prefer questions that could sustain a 5-15 minute explanation
- If a headline mentions a policy, law, technology, or scientific concept, the question should be about that concept, not the specific news event
- If a headline is about a person, the question should be about what they represent or why they matter, not biographical facts
- Sports game results, scores, player performances → SKIP
- Celebrity news without deeper societal angle → SKIP
- Weather updates, stock prices → SKIP

Items:
{items_text}

Respond in this exact format (one line per item, same numbering):
1. Why does [concept] work this way?
2. SKIP
3. How does [thing] actually affect [people]?
..."""

        try:
            response = self.groq_client.chat.completions.create(
                model="llama-3.3-70b-versatile",
                messages=[{"role": "user", "content": prompt}],
                max_tokens=2000,
                temperature=0.3
            )

            response_text = response.choices[0].message.content.strip()

            # Parse numbered responses
            results = []
            lines = response_text.split('\n')

            for line in lines:
                line = line.strip()
                if not line:
                    continue

                # Match pattern: "1. question" or "1) question"
                match = re.match(r'^(\d+)[.)\s]+(.+)$', line)
                if match:
                    idx = int(match.group(1)) - 1
                    question = match.group(2).strip()

                    if 0 <= idx < len(batch):
                        original = batch[idx].get("topic_name", "")
                        source = batch[idx].get("source", "unknown")

                        if question.upper() == "SKIP":
                            self.stats["skipped_by_llm"] += 1
                        else:
                            results.append((original, question, source))
                            self.stats["questions_generated"] += 1

            return results

        except Exception as e:
            self.errors.append(f"Groq batch error: {str(e)}")
            self.stats["groq_errors"] += 1
            return []

    def youtube_search_suggest(self, query: str) -> List[str]:
        """
        Get suggestions from YouTube search for a query.
        Used to validate if people are searching for the LLM-generated questions.
        """
        try:
            url = "https://suggestqueries.google.com/complete/search"
            params = {
                "client": "youtube",
                "ds": "yt",
                "q": query
            }
            response = requests.get(
                url,
                params=params,
                headers=self.headers,
                timeout=10
            )
            response.raise_for_status()

            text = response.text
            import json

            try:
                data = json.loads(text)
                if len(data) >= 2 and isinstance(data[1], list):
                    return data[1][:5]  # Return top 5 suggestions
            except json.JSONDecodeError:
                pass

            # Try to extract from JSONP format
            match = re.search(r'\[.*\]', text)
            if match:
                data = json.loads(match.group())
                if len(data) >= 2 and isinstance(data[1], list):
                    suggestions = []
                    for item in data[1]:
                        if isinstance(item, list) and len(item) > 0:
                            suggestions.append(item[0])
                        elif isinstance(item, str):
                            suggestions.append(item)
                    return suggestions[:5]

            return []

        except Exception as e:
            self.errors.append(f"YouTube suggest error for '{query[:30]}...': {str(e)}")
            return []

    def generate_queries_for_topics(
        self,
        topics: List[Dict[str, Any]],
        max_items: int = 150
    ) -> List[TrendItem]:
        """
        Generate curiosity queries from trending topics using Groq LLM.

        Args:
            topics: List of topic dicts with 'topic_name' and 'source' keys
            max_items: Maximum items to process through Groq

        Returns:
            List of TrendItem objects for generated questions
        """
        # Step 1: Separate and prioritize sources
        google_news = [t for t in topics if t.get("source") == "google_news"]
        google_trends = [t for t in topics if t.get("source") == "google_trends"]
        youtube = [t for t in topics if t.get("source") == "youtube"]

        print(f"    Input: {len(google_news)} news, {len(google_trends)} trends, {len(youtube)} videos")

        # Deduplicate headlines
        google_news = self._dedupe_headlines(google_news)
        print(f"    After dedup: {len(google_news)} unique news headlines")

        # Prioritize: news first, then trends, then videos (capped at max_items)
        combined = []
        combined.extend(google_news[:120])  # Most news
        combined.extend(google_trends[:20])  # All trends usually
        combined.extend(youtube[:10])  # Just a few videos

        combined = combined[:max_items]
        self.stats["items_sent_to_groq"] = len(combined)
        print(f"    Sending {len(combined)} items to Groq LLM...")

        # Step 2: Batch through Groq
        batches = self._batch_items(combined, batch_size=25)
        all_questions = []

        for i, batch in enumerate(batches):
            print(f"      Batch {i+1}/{len(batches)} ({len(batch)} items)...", end=" ")
            questions = self._call_groq_for_questions(batch)
            all_questions.extend(questions)
            print(f"{len(questions)} questions")

            # Delay between batches
            if i < len(batches) - 1:
                time.sleep(1)

        print(f"    Groq complete: {len(all_questions)} questions, {self.stats['skipped_by_llm']} skipped")

        # Step 3: Create TrendItems from questions
        items = []
        for original, question, source in all_questions:
            items.append(TrendItem(
                topic_name=question,
                source="curiosity_query",
                rank=len(items) + 1,
                region="global",
                timestamp=datetime.now(timezone.utc).isoformat(),
                url="",
                metadata={
                    "original_headline": original,
                    "original_source": source,
                    "llm_generated": True,
                    "query_source": "groq_llm"
                }
            ))

        # Step 4: Optional - YouTube suggest validation for top questions
        print(f"    Validating top 30 questions with YouTube suggest...")
        validated_count = 0
        for item in items[:30]:
            question = item.topic_name
            suggestions = self.youtube_search_suggest(question)

            if suggestions:
                validated_count += 1
                # Add YouTube suggestions as additional items
                for suggestion in suggestions[:2]:  # Max 2 per question
                    if suggestion.lower() != question.lower():
                        items.append(TrendItem(
                            topic_name=suggestion,
                            source="curiosity_query",
                            rank=len(items) + 1,
                            region="global",
                            timestamp=datetime.now(timezone.utc).isoformat(),
                            url="",
                            metadata={
                                "original_headline": item.metadata.get("original_headline", ""),
                                "original_source": item.metadata.get("original_source", ""),
                                "llm_generated": False,
                                "query_source": "youtube_suggest",
                                "validated_from": question
                            }
                        ))

            time.sleep(0.5)  # Rate limit

        self.stats["youtube_validated"] = validated_count
        print(f"    YouTube validation: {validated_count}/30 questions had suggestions")

        self.stats["queries_generated"] = len(items)
        print(f"    Total curiosity queries: {len(items)}")

        return items
