"""
Generate Content AI Function
STAGE 3: Updated to use final Stage 1 Content schema
"""
import logging
import re
from typing import Dict, List, Any
from django.db import transaction
from igny8_core.ai.base import BaseAIFunction
from igny8_core.modules.writer.models import Tasks, Content
from igny8_core.business.content.models import ContentTaxonomy
from igny8_core.ai.ai_core import AICore
from igny8_core.ai.validators import validate_tasks_exist
from igny8_core.ai.prompts import PromptRegistry
from igny8_core.ai.settings import get_model_config

logger = logging.getLogger(__name__)


class GenerateContentFunction(BaseAIFunction):
    """Generate content for tasks using AI"""
    
    def get_name(self) -> str:
        return 'generate_content'
    
    def get_metadata(self) -> Dict:
        return {
            'display_name': 'Generate Content',
            'description': 'Generate article content from task ideas',
            'phases': {
                'INIT': 'Initializing content generation...',
                'PREP': 'Loading tasks and building prompts...',
                'AI_CALL': 'Generating content with AI...',
                'PARSE': 'Processing content...',
                'SAVE': 'Saving content...',
                'DONE': 'Content generated!'
            }
        }
    
    def get_max_items(self) -> int:
        return 50  # Max tasks per batch
    
    def validate(self, payload: dict, account=None) -> Dict:
        """Validate task IDs"""
        result = super().validate(payload, account)
        if not result['valid']:
            return result
        
        # Check tasks exist
        task_ids = payload.get('ids', [])
        if task_ids:
            task_result = validate_tasks_exist(task_ids, account)
            if not task_result['valid']:
                return task_result
        
        return {'valid': True}
    
    def prepare(self, payload: dict, account=None) -> List:
        """Load tasks with all relationships"""
        task_ids = payload.get('ids', [])
        
        queryset = Tasks.objects.filter(id__in=task_ids)
        if account:
            queryset = queryset.filter(account=account)
        
        # STAGE 3: Preload relationships - taxonomy_term instead of taxonomy
        tasks = list(queryset.select_related(
            'account', 'site', 'sector', 'cluster', 'taxonomy_term'
        ))
        
        if not tasks:
            raise ValueError("No tasks found")
        
        return tasks
    
    def build_prompt(self, data: Any, account=None) -> str:
        """STAGE 3: Build content generation prompt using final Task schema"""
        if isinstance(data, list):
            if not data:
                raise ValueError("No tasks provided")
            task = data[0]
        else:
            task = data
        
        account = account or task.account
        
        # Build idea data string
        idea_data = f"Title: {task.title or 'Untitled'}\n"
        if task.description:
            idea_data += f"Description: {task.description}\n"
        
        # Add content type and structure from task
        idea_data += f"Content Type: {task.content_type or 'post'}\n"
        idea_data += f"Content Structure: {task.content_structure or 'article'}\n"
        
        # Build cluster data string
        cluster_data = ''
        if task.cluster:
            cluster_data = f"Cluster Name: {task.cluster.name or ''}\n"
            if task.cluster.description:
                cluster_data += f"Description: {task.cluster.description}\n"
        
        # STAGE 3: Build taxonomy context (from taxonomy_term FK)
        taxonomy_data = ''
        if task.taxonomy_term:
            taxonomy_data = f"Taxonomy: {task.taxonomy_term.name or ''}\n"
            if task.taxonomy_term.taxonomy_type:
                taxonomy_data += f"Type: {task.taxonomy_term.get_taxonomy_type_display()}\n"
        
        # STAGE 3: Build keywords context (from keywords TextField)
        keywords_data = ''
        if task.keywords:
            keywords_data = f"Keywords: {task.keywords}\n"
        
        # Get prompt from registry with context
        prompt = PromptRegistry.get_prompt(
            function_name='generate_content',
            account=account,
            task=task,
            context={
                'IDEA': idea_data,
                'CLUSTER': cluster_data,
                'TAXONOMY': taxonomy_data,
                'KEYWORDS': keywords_data,
            }
        )
        
        return prompt
    
    def parse_response(self, response: str, step_tracker=None) -> Dict:
        """Parse content response - can be JSON or plain text"""
        import json
        
        # Try to parse as JSON first
        try:
            parsed_json = json.loads(response.strip())
            if isinstance(parsed_json, dict):
                # It's a JSON object with structured data
                return parsed_json
        except (json.JSONDecodeError, ValueError):
            pass
        
        # If not JSON, treat as plain content and normalize
        try:
            from igny8_core.utils.content_normalizer import normalize_content
            normalized = normalize_content(response)
            content_text = normalized['normalized_content']
            # Return as dict with content field for consistency
            return {'content': content_text}
        except Exception as e:
            logger.warning(f"Content normalization failed: {e}, using original")
            return {'content': response}
    
    def save_output(
        self,
        parsed: Any,
        original_data: Any,
        account=None,
        progress_tracker=None,
        step_tracker=None
    ) -> Dict:
        """
        STAGE 3: Save content using final Stage 1 Content model schema.
        Creates independent Content record (no OneToOne to Task).
        Handles tags and categories from AI response.
        """
        if isinstance(original_data, list):
            task = original_data[0] if original_data else None
        else:
            task = original_data
        
        if not task:
            raise ValueError("No task provided for saving")
        
        # Handle parsed response - can be dict (JSON) or string (plain text)
        if isinstance(parsed, dict):
            # JSON response with structured fields
            content_html = parsed.get('content', '')
            title = parsed.get('title') or task.title
            meta_title = parsed.get('meta_title') or parsed.get('seo_title') or title
            meta_description = parsed.get('meta_description') or parsed.get('seo_description')
            primary_keyword = parsed.get('primary_keyword') or parsed.get('focus_keyword')
            secondary_keywords = parsed.get('secondary_keywords') or parsed.get('keywords', [])
            # Extract tags and categories from AI response
            tags_from_response = parsed.get('tags', [])
            categories_from_response = parsed.get('categories', [])
            
            # DEBUG: Log the full parsed response to see what we're getting
            logger.info(f"===== GENERATE CONTENT DEBUG =====")
            logger.info(f"Full parsed response keys: {list(parsed.keys())}")
            logger.info(f"Tags from response (type: {type(tags_from_response)}): {tags_from_response}")
            logger.info(f"Categories from response (type: {type(categories_from_response)}): {categories_from_response}")
            logger.info(f"==================================")
        else:
            # Plain text response
            content_html = str(parsed)
            title = task.title
            meta_title = title
            meta_description = None
            primary_keyword = None
            secondary_keywords = []
            tags_from_response = []
            categories_from_response = []
        
        # Calculate word count
        word_count = 0
        if content_html:
            text_for_counting = re.sub(r'<[^>]+>', '', content_html)
            word_count = len(text_for_counting.split())
        
        # STAGE 3: Create independent Content record using final schema
        content_record = Content.objects.create(
            # Core fields
            title=title,
            content_html=content_html or '',
            word_count=word_count,
            # SEO fields
            meta_title=meta_title,
            meta_description=meta_description,
            primary_keyword=primary_keyword,
            secondary_keywords=secondary_keywords if isinstance(secondary_keywords, list) else [],
            # Structure
            cluster=task.cluster,
            content_type=task.content_type,
            content_structure=task.content_structure,
            # Source and status
            source='igny8',
            status='draft',
            # Site/Sector/Account
            account=task.account,
            site=task.site,
            sector=task.sector,
        )
        
        logger.info(f"Created content record ID: {content_record.id}")
        logger.info(f"Processing taxonomies - Tags: {len(tags_from_response) if tags_from_response else 0}, Categories: {len(categories_from_response) if categories_from_response else 0}")
        
        # Link taxonomy terms from task if available
        if task.taxonomy_term:
            content_record.taxonomy_terms.add(task.taxonomy_term)
            logger.info(f"Added task taxonomy term: {task.taxonomy_term.name}")
        
        # Process tags from AI response
        logger.info(f"Starting tag processing: {tags_from_response}")
        if tags_from_response and isinstance(tags_from_response, list):
            from django.utils.text import slugify
            for tag_name in tags_from_response:
                logger.info(f"Processing tag: '{tag_name}' (type: {type(tag_name)})")
                if tag_name and isinstance(tag_name, str):
                    tag_name = tag_name.strip()
                    if tag_name:
                        try:
                            tag_slug = slugify(tag_name)
                            logger.info(f"Creating/finding tag: name='{tag_name}', slug='{tag_slug}'")
                            # Get or create tag taxonomy term using site + slug + type for uniqueness
                            tag_obj, created = ContentTaxonomy.objects.get_or_create(
                                site=task.site,
                                slug=tag_slug,
                                taxonomy_type='tag',
                                defaults={
                                    'name': tag_name,
                                    'sector': task.sector,
                                    'account': task.account,
                                    'description': '',
                                    'external_taxonomy': '',
                                    'sync_status': '',
                                    'count': 0,
                                    'metadata': {},
                                }
                            )
                            content_record.taxonomy_terms.add(tag_obj)
                            logger.info(f"✅ {'Created' if created else 'Found'} and linked tag: {tag_name} (ID: {tag_obj.id}, Slug: {tag_slug})")
                        except Exception as e:
                            logger.error(f"❌ Failed to add tag '{tag_name}': {e}", exc_info=True)
                else:
                    logger.warning(f"Skipping invalid tag: '{tag_name}' (type: {type(tag_name)})")
        else:
            logger.info(f"No tags to process or tags_from_response is not a list: {type(tags_from_response)}")
        
        # Process categories from AI response
        logger.info(f"Starting category processing: {categories_from_response}")
        if categories_from_response and isinstance(categories_from_response, list):
            from django.utils.text import slugify
            for category_name in categories_from_response:
                logger.info(f"Processing category: '{category_name}' (type: {type(category_name)})")
                if category_name and isinstance(category_name, str):
                    category_name = category_name.strip()
                    if category_name:
                        try:
                            category_slug = slugify(category_name)
                            logger.info(f"Creating/finding category: name='{category_name}', slug='{category_slug}'")
                            # Get or create category taxonomy term using site + slug + type for uniqueness
                            category_obj, created = ContentTaxonomy.objects.get_or_create(
                                site=task.site,
                                slug=category_slug,
                                taxonomy_type='category',
                                defaults={
                                    'name': category_name,
                                    'sector': task.sector,
                                    'account': task.account,
                                    'description': '',
                                    'external_taxonomy': '',
                                    'sync_status': '',
                                    'count': 0,
                                    'metadata': {},
                                }
                            )
                            content_record.taxonomy_terms.add(category_obj)
                            logger.info(f"✅ {'Created' if created else 'Found'} and linked category: {category_name} (ID: {category_obj.id}, Slug: {category_slug})")
                        except Exception as e:
                            logger.error(f"❌ Failed to add category '{category_name}': {e}", exc_info=True)
                else:
                    logger.warning(f"Skipping invalid category: '{category_name}' (type: {type(category_name)})")
        else:
            logger.info(f"No categories to process or categories_from_response is not a list: {type(categories_from_response)}")
        
        # STAGE 3: Update task status to completed
        task.status = 'completed'
        task.save(update_fields=['status', 'updated_at'])
        
        # NEW: Auto-sync idea status from task status
        if hasattr(task, 'idea') and task.idea:
            task.idea.status = 'completed'
            task.idea.save(update_fields=['status', 'updated_at'])
            logger.info(f"Updated related idea ID {task.idea.id} to completed")
        
        return {
            'count': 1,
            'content_id': content_record.id,
            'task_id': task.id,
            'word_count': word_count,
        }


