"""
Tests for OptimizeContentFunction
"""
from unittest.mock import Mock, patch, MagicMock
from django.test import TestCase
from igny8_core.business.content.models import Content
from igny8_core.ai.functions.optimize_content import OptimizeContentFunction
from igny8_core.api.tests.test_integration_base import IntegrationTestBase


class OptimizeContentFunctionTests(IntegrationTestBase):
    """Tests for OptimizeContentFunction"""
    
    def setUp(self):
        super().setUp()
        self.function = OptimizeContentFunction()
        
        # Create test content
        self.content = Content.objects.create(
            account=self.account,
            site=self.site,
            sector=self.sector,
            title="Test Content",
            html_content="<p>This is test content.</p>",
            meta_title="Test Title",
            meta_description="Test description",
            primary_keyword="test keyword",
            word_count=500,
            status='draft'
        )
    
    def test_function_validation_phase(self):
        """Test validation phase"""
        # Valid payload
        result = self.function.validate({'ids': [self.content.id]}, self.account)
        self.assertTrue(result['valid'])
        
        # Invalid payload - missing ids
        result = self.function.validate({}, self.account)
        self.assertFalse(result['valid'])
        self.assertIn('error', result)
    
    def test_function_prep_phase(self):
        """Test prep phase"""
        payload = {'ids': [self.content.id]}
        
        data = self.function.prepare(payload, self.account)
        
        self.assertIn('content', data)
        self.assertIn('scores_before', data)
        self.assertIn('html_content', data)
        self.assertEqual(data['content'].id, self.content.id)
    
    def test_function_prep_phase_content_not_found(self):
        """Test prep phase with non-existent content"""
        payload = {'ids': [99999]}
        
        with self.assertRaises(ValueError):
            self.function.prepare(payload, self.account)
    
    @patch('igny8_core.ai.functions.optimize_content.PromptRegistry.get_prompt')
    def test_function_build_prompt(self, mock_get_prompt):
        """Test prompt building"""
        mock_get_prompt.return_value = "Test prompt"
        
        data = {
            'content': self.content,
            'html_content': '<p>Test</p>',
            'meta_title': 'Title',
            'meta_description': 'Description',
            'primary_keyword': 'keyword',
            'scores_before': {'overall_score': 50.0}
        }
        
        prompt = self.function.build_prompt(data, self.account)
        
        self.assertEqual(prompt, "Test prompt")
        mock_get_prompt.assert_called_once()
        # Check that context was passed
        call_args = mock_get_prompt.call_args
        self.assertIn('context', call_args.kwargs)
    
    def test_function_parse_response_valid_json(self):
        """Test parsing valid JSON response"""
        response = '{"html_content": "<p>Optimized</p>", "meta_title": "New Title"}'
        
        parsed = self.function.parse_response(response)
        
        self.assertIn('html_content', parsed)
        self.assertEqual(parsed['html_content'], "<p>Optimized</p>")
        self.assertEqual(parsed['meta_title'], "New Title")
    
    def test_function_parse_response_invalid_json(self):
        """Test parsing invalid JSON response"""
        response = "This is not JSON"
        
        with self.assertRaises(ValueError):
            self.function.parse_response(response)
    
    def test_function_parse_response_extracts_json_object(self):
        """Test that JSON object is extracted from text"""
        response = 'Some text {"html_content": "<p>Optimized</p>"} more text'
        
        parsed = self.function.parse_response(response)
        
        self.assertIn('html_content', parsed)
        self.assertEqual(parsed['html_content'], "<p>Optimized</p>")
    
    @patch('igny8_core.business.optimization.services.analyzer.ContentAnalyzer.analyze')
    @patch('igny8_core.business.content.services.content_generation_service.ContentGenerationService._count_words')
    def test_function_save_phase(self, mock_count_words, mock_analyze):
        """Test save phase updates content"""
        mock_count_words.return_value = 600
        mock_analyze.return_value = {
            'seo_score': 75.0,
            'readability_score': 80.0,
            'engagement_score': 70.0,
            'overall_score': 75.0
        }
        
        parsed = {
            'html_content': '<p>Optimized content.</p>',
            'meta_title': 'Optimized Title',
            'meta_description': 'Optimized Description'
        }
        
        original_data = {
            'content': self.content,
            'scores_before': {'overall_score': 50.0},
            'word_count': 500
        }
        
        result = self.function.save_output(parsed, original_data, self.account)
        
        self.assertTrue(result['success'])
        self.assertEqual(result['content_id'], self.content.id)
        
        # Refresh content from DB
        self.content.refresh_from_db()
        self.assertEqual(self.content.html_content, '<p>Optimized content.</p>')
        self.assertEqual(self.content.optimizer_version, 1)
        self.assertIsNotNone(self.content.optimization_scores)
    
    def test_function_handles_invalid_content_id(self):
        """Test that function handles invalid content ID"""
        payload = {'ids': [99999]}
        
        with self.assertRaises(ValueError):
            self.function.prepare(payload, self.account)
    
    def test_function_respects_account_isolation(self):
        """Test that function respects account isolation"""
        from igny8_core.auth.models import Account
        other_account = Account.objects.create(
            name="Other Account",
            slug="other",
            plan=self.plan,
            owner=self.user
        )
        
        payload = {'ids': [self.content.id]}
        
        # Should not find content from different account
        with self.assertRaises(ValueError):
            self.function.prepare(payload, other_account)
    
    def test_get_name(self):
        """Test get_name method"""
        self.assertEqual(self.function.get_name(), 'optimize_content')
    
    def test_get_metadata(self):
        """Test get_metadata method"""
        metadata = self.function.get_metadata()
        
        self.assertIn('display_name', metadata)
        self.assertIn('description', metadata)
        self.assertIn('phases', metadata)
        self.assertEqual(metadata['display_name'], 'Optimize Content')

