"""
Tests for Universal Content Types Linking (Phase 8)
Tests for product and taxonomy linking
"""
from unittest.mock import patch, MagicMock
from django.test import TestCase
from igny8_core.business.content.models import Content
from igny8_core.business.linking.services.linker_service import LinkerService
from igny8_core.api.tests.test_integration_base import IntegrationTestBase


class UniversalContentLinkingTests(IntegrationTestBase):
    """Tests for Phase 8: Universal Content Types Linking"""
    
    def setUp(self):
        super().setUp()
        # Add credits to account for testing
        self.account.credits = 10000
        self.account.save()
        self.linker_service = LinkerService()
        
        # Create product content
        self.product_content = Content.objects.create(
            account=self.account,
            site=self.site,
            sector=self.sector,
            title='Test Product',
            html_content='<p>Product content with features and specifications.</p>',
            entity_type='product',
            json_blocks=[
                {'type': 'features', 'heading': 'Features', 'items': ['Feature 1', 'Feature 2']}
            ],
            structure_data={'product_type': 'software'},
            word_count=1500,
            status='draft'
        )
        
        # Create related product
        self.related_product = Content.objects.create(
            account=self.account,
            site=self.site,
            sector=self.sector,
            title='Related Product',
            html_content='<p>Related product content.</p>',
            entity_type='product',
            structure_data={'product_type': 'software'},
            word_count=1500,
            status='draft'
        )
        
        # Create service content
        self.service_content = Content.objects.create(
            account=self.account,
            site=self.site,
            sector=self.sector,
            title='Related Service',
            html_content='<p>Service content.</p>',
            entity_type='service',
            word_count=1800,
            status='draft'
        )
        
        # Create taxonomy content
        self.taxonomy_content = Content.objects.create(
            account=self.account,
            site=self.site,
            sector=self.sector,
            title='Test Taxonomy',
            html_content='<p>Taxonomy content with categories.</p>',
            entity_type='taxonomy',
            json_blocks=[
                {
                    'type': 'categories',
                    'heading': 'Categories',
                    'items': [
                        {'name': 'Category 1', 'description': 'Desc 1', 'subcategories': []}
                    ]
                }
            ],
            word_count=1200,
            status='draft'
        )
        
        # Create related taxonomy
        self.related_taxonomy = Content.objects.create(
            account=self.account,
            site=self.site,
            sector=self.sector,
            title='Related Taxonomy',
            html_content='<p>Related taxonomy content.</p>',
            entity_type='taxonomy',
            word_count=1200,
            status='draft'
        )
    
    @patch('igny8_core.business.linking.services.linker_service.InjectionEngine.inject_links')
    @patch('igny8_core.business.linking.services.linker_service.CreditService.check_credits')
    @patch('igny8_core.business.linking.services.linker_service.CreditService.deduct_credits_for_operation')
    def test_linking_works_for_products(self, mock_deduct, mock_check_credits, mock_inject_links):
        """
        Test: Linking works for all content types (products, taxonomies)
        Task 20: Verify product linking finds related products and services
        """
        # Mock injection engine
        mock_inject_links.return_value = {
            'html_content': '<p>Product content with links.</p>',
            'links': [
                {'content_id': self.related_product.id, 'anchor_text': 'Related Product'},
                {'content_id': self.service_content.id, 'anchor_text': 'Related Service'}
            ],
            'links_added': 2
        }
        
        # Process product linking
        result = self.linker_service.process_product(self.product_content.id)
        
        # Verify result
        self.assertIsNotNone(result)
        self.assertEqual(result.entity_type, 'product')
        self.assertIsNotNone(result.internal_links)
        self.assertEqual(len(result.internal_links), 2)
        self.assertEqual(result.linker_version, 1)
        
        # Verify injection was called
        mock_inject_links.assert_called_once()
        candidates = mock_inject_links.call_args[0][1]
        self.assertGreater(len(candidates), 0)
        
        # Verify product candidates were found
        product_candidates = [c for c in candidates if c.get('content_id') == self.related_product.id]
        self.assertGreater(len(product_candidates), 0)
    
    @patch('igny8_core.business.linking.services.linker_service.InjectionEngine.inject_links')
    @patch('igny8_core.business.linking.services.linker_service.CreditService.check_credits')
    @patch('igny8_core.business.linking.services.linker_service.CreditService.deduct_credits_for_operation')
    def test_linking_works_for_taxonomies(self, mock_deduct, mock_check_credits, mock_inject_links):
        """
        Test: Linking works for all content types (products, taxonomies)
        Task 20: Verify taxonomy linking finds related taxonomies and content
        """
        # Mock injection engine
        mock_inject_links.return_value = {
            'html_content': '<p>Taxonomy content with links.</p>',
            'links': [
                {'content_id': self.related_taxonomy.id, 'anchor_text': 'Related Taxonomy'}
            ],
            'links_added': 1
        }
        
        # Process taxonomy linking
        result = self.linker_service.process_taxonomy(self.taxonomy_content.id)
        
        # Verify result
        self.assertIsNotNone(result)
        self.assertEqual(result.entity_type, 'taxonomy')
        self.assertIsNotNone(result.internal_links)
        self.assertEqual(len(result.internal_links), 1)
        self.assertEqual(result.linker_version, 1)
        
        # Verify injection was called
        mock_inject_links.assert_called_once()
        candidates = mock_inject_links.call_args[0][1]
        self.assertGreater(len(candidates), 0)
        
        # Verify taxonomy candidates were found
        taxonomy_candidates = [c for c in candidates if c.get('content_id') == self.related_taxonomy.id]
        self.assertGreater(len(taxonomy_candidates), 0)
    
    def test_product_linking_finds_related_products(self):
        """
        Test: Linking works for all content types (products, taxonomies)
        Task 20: Verify _find_product_candidates finds related products
        """
        candidates = self.linker_service._find_product_candidates(self.product_content)
        
        # Should find related product
        product_ids = [c['content_id'] for c in candidates]
        self.assertIn(self.related_product.id, product_ids)
        
        # Should find related service
        self.assertIn(self.service_content.id, product_ids)
    
    def test_taxonomy_linking_finds_related_taxonomies(self):
        """
        Test: Linking works for all content types (products, taxonomies)
        Task 20: Verify _find_taxonomy_candidates finds related taxonomies
        """
        candidates = self.linker_service._find_taxonomy_candidates(self.taxonomy_content)
        
        # Should find related taxonomy
        taxonomy_ids = [c['content_id'] for c in candidates]
        self.assertIn(self.related_taxonomy.id, taxonomy_ids)

