"""
Introduction Generator - Generates varied blog introductions based on content and research.

Generates 3 different introduction options for the user to choose from.
"""

from typing import Dict, Any, List
from loguru import logger

from models.blog_models import BlogResearchResponse, BlogOutlineSection


class IntroductionGenerator:
    """Generates blog introductions using research and content data."""
    
    def __init__(self):
        """Initialize the introduction generator."""
        pass
    
    def build_introduction_prompt(
        self,
        blog_title: str,
        research: BlogResearchResponse,
        outline: List[BlogOutlineSection],
        sections_content: Dict[str, str],
        primary_keywords: List[str],
        search_intent: str
    ) -> str:
        """Build a prompt for generating blog introductions."""
        
        # Extract key research insights
        keyword_analysis = research.keyword_analysis or {}
        content_angles = research.suggested_angles or []
        
        # Get a summary of the first few sections for context
        section_summaries = []
        for i, section in enumerate(outline[:3], 1):
            section_id = section.id
            content = sections_content.get(section_id, '')
            if content:
                # Take first 200 chars as summary
                summary = content[:200] + '...' if len(content) > 200 else content
                section_summaries.append(f"{i}. {section.heading}: {summary}")
        
        sections_text = '\n'.join(section_summaries) if section_summaries else "Content sections are being generated."
        
        primary_kw_text = ', '.join(primary_keywords) if primary_keywords else "the topic"
        content_angle_text = ', '.join(content_angles[:3]) if content_angles else "General insights"
        
        return f"""Generate exactly 3 varied blog introductions for the following blog post.

BLOG TITLE: {blog_title}

PRIMARY KEYWORDS: {primary_kw_text}
SEARCH INTENT: {search_intent}
CONTENT ANGLES: {content_angle_text}

BLOG CONTENT SUMMARY:
{sections_text}

REQUIREMENTS FOR EACH INTRODUCTION:
- 80-120 words in length
- Hook the reader immediately with a compelling opening
- Clearly state the value proposition and what readers will learn
- Include the primary keyword naturally within the first 2 sentences
- Each introduction should have a different angle/approach:
  1. First: Problem-focused (highlight the challenge readers face)
  2. Second: Benefit-focused (emphasize the value and outcomes)
  3. Third: Story/statistic-focused (use a compelling fact or narrative hook)
- Maintain a professional yet engaging tone
- Avoid generic phrases - be specific and benefit-driven

Return ONLY a JSON array of exactly 3 introductions:
[
  "First introduction (80-120 words, problem-focused)",
  "Second introduction (80-120 words, benefit-focused)",
  "Third introduction (80-120 words, story/statistic-focused)"
]"""
    
    def get_introduction_schema(self) -> Dict[str, Any]:
        """Get the JSON schema for introduction generation."""
        return {
            "type": "array",
            "items": {
                "type": "string",
                "minLength": 80,
                "maxLength": 150
            },
            "minItems": 3,
            "maxItems": 3
        }
    
    async def generate_introductions(
        self,
        blog_title: str,
        research: BlogResearchResponse,
        outline: List[BlogOutlineSection],
        sections_content: Dict[str, str],
        primary_keywords: List[str],
        search_intent: str,
        user_id: str
    ) -> List[str]:
        """Generate 3 varied blog introductions.
        
        Args:
            blog_title: The blog post title
            research: Research data with keywords and insights
            outline: Blog outline sections
            sections_content: Dictionary mapping section IDs to their content
            primary_keywords: Primary keywords for the blog
            search_intent: Search intent (informational, commercial, etc.)
            user_id: User ID for API calls
            
        Returns:
            List of 3 introduction options
        """
        from services.llm_providers.main_text_generation import llm_text_gen
        
        if not user_id:
            raise ValueError("user_id is required for introduction generation")
        
        # Build prompt
        prompt = self.build_introduction_prompt(
            blog_title=blog_title,
            research=research,
            outline=outline,
            sections_content=sections_content,
            primary_keywords=primary_keywords,
            search_intent=search_intent
        )
        
        # Get schema
        schema = self.get_introduction_schema()
        
        logger.info(f"Generating blog introductions for user {user_id}")
        
        try:
            # Generate introductions using structured JSON response
            result = llm_text_gen(
                prompt=prompt,
                json_struct=schema,
                system_prompt="You are an expert content writer specializing in creating compelling blog introductions that hook readers and clearly communicate value.",
                user_id=user_id
            )
            
            # Handle response - could be array directly or wrapped in dict
            if isinstance(result, list):
                introductions = result
            elif isinstance(result, dict):
                # Try common keys
                introductions = result.get('introductions', result.get('options', result.get('intros', [])))
                if not introductions and isinstance(result.get('response'), list):
                    introductions = result['response']
            else:
                logger.warning(f"Unexpected introduction generation result type: {type(result)}")
                introductions = []
            
            # Validate and clean introductions
            cleaned_introductions = []
            for intro in introductions:
                if isinstance(intro, str) and len(intro.strip()) >= 50:  # Minimum reasonable length
                    cleaned = intro.strip()
                    # Ensure it's within reasonable bounds
                    if len(cleaned) <= 200:  # Allow slight overflow for quality
                        cleaned_introductions.append(cleaned)
            
            # Ensure we have exactly 3 introductions
            if len(cleaned_introductions) < 3:
                logger.warning(f"Generated only {len(cleaned_introductions)} introductions, expected 3")
                # Pad with placeholder if needed
                while len(cleaned_introductions) < 3:
                    cleaned_introductions.append(f"{blog_title} - A comprehensive guide covering essential insights and practical strategies.")
            
            # Return exactly 3 introductions
            return cleaned_introductions[:3]
            
        except Exception as e:
            logger.error(f"Failed to generate introductions: {e}")
            # Fallback: generate simple introductions
            fallback_introductions = [
                f"In this comprehensive guide, we'll explore {primary_keywords[0] if primary_keywords else 'essential insights'} and provide actionable strategies.",
                f"Discover everything you need to know about {primary_keywords[0] if primary_keywords else 'this topic'} and how it can transform your approach.",
                f"Whether you're new to {primary_keywords[0] if primary_keywords else 'this topic'} or looking to deepen your understanding, this guide has you covered."
            ]
            return fallback_introductions

