"""
Content Analyzer
Analyzes content quality and calculates optimization scores
"""
import logging
import re
from typing import Dict
from igny8_core.business.content.models import Content

logger = logging.getLogger(__name__)


class ContentAnalyzer:
    """Analyzes content quality"""
    
    def analyze(self, content: Content) -> Dict:
        """
        Analyze content and return scores.
        
        Args:
            content: Content instance to analyze
        
        Returns:
            Dict with scores: {'seo_score', 'readability_score', 'engagement_score', 'overall_score'}
        """
        if not content or not content.html_content:
            return {
                'seo_score': 0,
                'readability_score': 0,
                'engagement_score': 0,
                'overall_score': 0
            }
        
        seo_score = self._calculate_seo_score(content)
        readability_score = self._calculate_readability_score(content)
        engagement_score = self._calculate_engagement_score(content)
        
        # Stage 3: Calculate metadata completeness score
        metadata_score = self._calculate_metadata_score(content)
        
        # Overall score is weighted average (includes metadata)
        overall_score = (
            seo_score * 0.35 +
            readability_score * 0.25 +
            engagement_score * 0.25 +
            metadata_score * 0.15
        )
        
        return {
            'seo_score': round(seo_score, 2),
            'readability_score': round(readability_score, 2),
            'engagement_score': round(engagement_score, 2),
            'metadata_score': round(metadata_score, 2),  # Stage 3: Add metadata score
            'overall_score': round(overall_score, 2),
            'word_count': content.word_count or 0,
            'has_meta_title': bool(content.meta_title),
            'has_meta_description': bool(content.meta_description),
            'has_primary_keyword': bool(content.primary_keyword),
            'internal_links_count': len(content.internal_links) if content.internal_links else 0,
            # Stage 3: Metadata completeness indicators
            'has_entity_type': bool(content.entity_type),
            'has_cluster_mapping': self._has_cluster_mapping(content),
            'has_taxonomy_mapping': self._has_taxonomy_mapping(content),
        }
    
    def _calculate_metadata_score(self, content: Content) -> float:
        """Stage 3: Calculate metadata completeness score (0-100)"""
        score = 0
        
        # Entity type (20 points)
        if content.entity_type:
            score += 20
        
        # Cluster mapping (30 points)
        if self._has_cluster_mapping(content):
            score += 30
        
        # Taxonomy mapping (30 points) - required for products/services
        if self._has_taxonomy_mapping(content):
            score += 30
        elif content.entity_type in ['product', 'service']:
            # Products/services must have taxonomy
            score += 0
        else:
            # Other types get partial credit
            score += 15
        
        # Attributes (20 points) - for products
        if content.entity_type == 'product':
            from igny8_core.business.content.models import ContentAttributeMap
            attr_count = ContentAttributeMap.objects.filter(content=content).count()
            if attr_count >= 3:
                score += 20
            elif attr_count >= 1:
                score += 10
        
        return min(score, 100)
    
    def _has_cluster_mapping(self, content: Content) -> bool:
        """Stage 3: Check if content has cluster mapping"""
        from igny8_core.business.content.models import ContentClusterMap
        return ContentClusterMap.objects.filter(content=content).exists()
    
    def _has_taxonomy_mapping(self, content: Content) -> bool:
        """Stage 3: Check if content has taxonomy mapping (categories/tags)"""
        return content.taxonomy_terms.exists()
    
    def _calculate_seo_score(self, content: Content) -> float:
        """Calculate SEO score (0-100)"""
        score = 0
        
        # Meta title (20 points)
        if content.meta_title:
            if len(content.meta_title) >= 30 and len(content.meta_title) <= 60:
                score += 20
            elif len(content.meta_title) > 0:
                score += 10
        
        # Meta description (20 points)
        if content.meta_description:
            if len(content.meta_description) >= 120 and len(content.meta_description) <= 160:
                score += 20
            elif len(content.meta_description) > 0:
                score += 10
        
        # Primary keyword (20 points)
        if content.primary_keyword:
            score += 20
        
        # Word count (20 points) - optimal range 1000-2500 words
        word_count = content.word_count or 0
        if 1000 <= word_count <= 2500:
            score += 20
        elif 500 <= word_count < 1000 or 2500 < word_count <= 3000:
            score += 15
        elif word_count > 0:
            score += 10
        
        # Internal links (20 points)
        internal_links = content.internal_links or []
        if len(internal_links) >= 3:
            score += 20
        elif len(internal_links) >= 1:
            score += 10
        
        return min(score, 100)
    
    def _calculate_readability_score(self, content: Content) -> float:
        """Calculate readability score (0-100)"""
        if not content.html_content:
            return 0
        
        # Simple readability metrics
        html = content.html_content
        
        # Remove HTML tags for text analysis
        text = re.sub(r'<[^>]+>', '', html)
        sentences = re.split(r'[.!?]+', text)
        words = text.split()
        
        if not words:
            return 0
        
        # Average sentence length (optimal: 15-20 words)
        avg_sentence_length = len(words) / max(len(sentences), 1)
        if 15 <= avg_sentence_length <= 20:
            sentence_score = 40
        elif 10 <= avg_sentence_length < 15 or 20 < avg_sentence_length <= 25:
            sentence_score = 30
        else:
            sentence_score = 20
        
        # Average word length (optimal: 4-5 characters)
        avg_word_length = sum(len(word) for word in words) / len(words)
        if 4 <= avg_word_length <= 5:
            word_score = 30
        elif 3 <= avg_word_length < 4 or 5 < avg_word_length <= 6:
            word_score = 20
        else:
            word_score = 10
        
        # Paragraph structure (30 points)
        paragraphs = html.count('<p>') + html.count('<div>')
        if paragraphs >= 3:
            paragraph_score = 30
        elif paragraphs >= 1:
            paragraph_score = 20
        else:
            paragraph_score = 10
        
        return min(sentence_score + word_score + paragraph_score, 100)
    
    def _calculate_engagement_score(self, content: Content) -> float:
        """Calculate engagement score (0-100)"""
        score = 0
        
        # Headings (30 points)
        if content.html_content:
            h1_count = content.html_content.count('<h1>')
            h2_count = content.html_content.count('<h2>')
            h3_count = content.html_content.count('<h3>')
            
            if h1_count >= 1 and h2_count >= 2:
                score += 30
            elif h1_count >= 1 or h2_count >= 1:
                score += 20
            elif h3_count >= 1:
                score += 10
        
        # Images (30 points)
        if hasattr(content, 'images'):
            image_count = content.images.count()
            if image_count >= 3:
                score += 30
            elif image_count >= 1:
                score += 20
        
        # Lists (20 points)
        if content.html_content:
            list_count = content.html_content.count('<ul>') + content.html_content.count('<ol>')
            if list_count >= 2:
                score += 20
            elif list_count >= 1:
                score += 10
        
        # Internal links (20 points)
        internal_links = content.internal_links or []
        if len(internal_links) >= 3:
            score += 20
        elif len(internal_links) >= 1:
            score += 10
        
        return min(score, 100)


