"""
Optimize Content AI Function
Phase 4 – Linker & Optimizer
"""
import json
import logging
from typing import Any, Dict

from igny8_core.ai.base import BaseAIFunction
from igny8_core.ai.prompts import PromptRegistry
from igny8_core.business.content.models import Content

logger = logging.getLogger(__name__)


class OptimizeContentFunction(BaseAIFunction):
    """AI function that optimizes content for SEO, readability, and engagement."""

    def get_name(self) -> str:
        return 'optimize_content'

    def get_metadata(self) -> Dict:
        metadata = super().get_metadata()
        metadata.update({
            'display_name': 'Optimize Content',
            'description': 'Optimize content for SEO, readability, and engagement.',
            'phases': {
                'INIT': 'Validating content data…',
                'PREP': 'Preparing content context…',
                'AI_CALL': 'Optimizing content with AI…',
                'PARSE': 'Parsing optimized content…',
                'SAVE': 'Saving optimized content…',
                'DONE': 'Content optimized!'
            }
        })
        return metadata

    def validate(self, payload: dict, account=None) -> Dict[str, Any]:
        if not payload.get('ids'):
            return {'valid': False, 'error': 'Content ID is required'}
        return {'valid': True}

    def prepare(self, payload: dict, account=None) -> Dict[str, Any]:
        content_ids = payload.get('ids', [])
        queryset = Content.objects.filter(id__in=content_ids)
        if account:
            queryset = queryset.filter(account=account)
        content = queryset.select_related('account', 'site', 'sector').first()
        if not content:
            raise ValueError("Content not found")

        # Get current scores from analyzer
        from igny8_core.business.optimization.services.analyzer import ContentAnalyzer
        analyzer = ContentAnalyzer()
        scores_before = analyzer.analyze(content)

        return {
            'content': content,
            'scores_before': scores_before,
            'html_content': content.html_content or '',
            'meta_title': content.meta_title or '',
            'meta_description': content.meta_description or '',
            'primary_keyword': content.primary_keyword or '',
        }

    def build_prompt(self, data: Dict[str, Any], account=None) -> str:
        content: Content = data['content']
        scores_before = data.get('scores_before', {})
        
        context = {
            'CONTENT_TITLE': content.title or 'Untitled',
            'HTML_CONTENT': data.get('html_content', ''),
            'META_TITLE': data.get('meta_title', ''),
            'META_DESCRIPTION': data.get('meta_description', ''),
            'PRIMARY_KEYWORD': data.get('primary_keyword', ''),
            'WORD_COUNT': str(content.word_count or 0),
            'CURRENT_SCORES': json.dumps(scores_before, indent=2),
            'SOURCE': content.source,
            'INTERNAL_LINKS_COUNT': str(len(content.internal_links) if content.internal_links else 0),
        }

        return PromptRegistry.get_prompt(
            'optimize_content',
            account=account or content.account,
            context=context
        )

    def parse_response(self, response: str, step_tracker=None) -> Dict[str, Any]:
        if not response:
            raise ValueError("AI response is empty")

        response = response.strip()
        try:
            return self._ensure_dict(json.loads(response))
        except json.JSONDecodeError:
            logger.warning("Response not valid JSON, attempting to extract JSON object")
            cleaned = self._extract_json_object(response)
            if cleaned:
                return self._ensure_dict(json.loads(cleaned))
            raise ValueError("Unable to parse AI response into JSON")

    def save_output(
        self,
        parsed: Dict[str, Any],
        original_data: Dict[str, Any],
        account=None,
        progress_tracker=None,
        step_tracker=None
    ) -> Dict[str, Any]:
        content: Content = original_data['content']
        
        # Extract optimized content
        optimized_html = parsed.get('html_content') or parsed.get('content') or content.html_content
        optimized_meta_title = parsed.get('meta_title') or content.meta_title
        optimized_meta_description = parsed.get('meta_description') or content.meta_description
        
        # Update content
        content.html_content = optimized_html
        if optimized_meta_title:
            content.meta_title = optimized_meta_title
        if optimized_meta_description:
            content.meta_description = optimized_meta_description
        
        # Recalculate word count
        from igny8_core.business.content.services.content_generation_service import ContentGenerationService
        content_service = ContentGenerationService()
        content.word_count = content_service._count_words(optimized_html)
        
        # Increment optimizer version
        content.optimizer_version += 1
        
        # Get scores after optimization
        from igny8_core.business.optimization.services.analyzer import ContentAnalyzer
        analyzer = ContentAnalyzer()
        scores_after = analyzer.analyze(content)
        content.optimization_scores = scores_after
        
        content.save(update_fields=[
            'html_content', 'meta_title', 'meta_description', 
            'word_count', 'optimizer_version', 'optimization_scores', 'updated_at'
        ])

        return {
            'success': True,
            'content_id': content.id,
            'scores_before': original_data.get('scores_before', {}),
            'scores_after': scores_after,
            'word_count_before': original_data.get('word_count', 0),
            'word_count_after': content.word_count,
            'html_content': optimized_html,
            'meta_title': optimized_meta_title,
            'meta_description': optimized_meta_description,
        }

    # Helper methods
    def _ensure_dict(self, data: Any) -> Dict[str, Any]:
        if isinstance(data, dict):
            return data
        raise ValueError("AI response must be a JSON object")

    def _extract_json_object(self, text: str) -> str:
        start = text.find('{')
        end = text.rfind('}')
        if start != -1 and end != -1 and end > start:
            return text[start:end + 1]
        return ''

