"""
Comprehensive tests for version differentiation in the Blender text texture generator addon.

Tests the quadruple-layer detection system:
1. Template-generated constants (VERSION_TYPE, is_free_version(), ENABLED_FEATURES)
2. Runtime import detection flags (PRESETS_AVAILABLE, UTILITY_OPERATORS_AVAILABLE)
3. Version limits (get_version_limits() returns correct values)
4. UI helper functions (version display and feature gating)
"""

import pytest
import sys
from unittest.mock import Mock, patch, MagicMock
from types import ModuleType


class TestVersionDetection:
    """Test suite for version detection methods."""
    
    def test_version_type_constant(self):
        """Test VERSION_TYPE constant is properly set."""
        from src.utils.constants import VERSION_TYPE
        assert VERSION_TYPE in ["free", "full"], f"VERSION_TYPE should be 'free' or 'full', got '{VERSION_TYPE}'"
    
    def test_is_free_version_function(self):
        """Test is_free_version() function returns correct boolean."""
        from src.utils.constants import is_free_version, VERSION_TYPE
        
        result = is_free_version()
        assert isinstance(result, bool), "is_free_version() should return a boolean"
        
        # Result should match VERSION_TYPE
        expected = VERSION_TYPE == "free"
        assert result == expected, f"is_free_version() returned {result}, expected {expected} based on VERSION_TYPE='{VERSION_TYPE}'"
    
    def test_is_full_version_function(self):
        """Test is_full_version() function returns correct boolean."""
        from src.utils.constants import is_full_version, VERSION_TYPE
        
        result = is_full_version()
        assert isinstance(result, bool), "is_full_version() should return a boolean"
        
        # Result should match VERSION_TYPE
        expected = VERSION_TYPE == "full"
        assert result == expected, f"is_full_version() returned {result}, expected {expected} based on VERSION_TYPE='{VERSION_TYPE}'"
    
    def test_enabled_features_list(self):
        """Test ENABLED_FEATURES contains appropriate features for version."""
        from src.utils.constants import ENABLED_FEATURES, VERSION_TYPE
        
        assert isinstance(ENABLED_FEATURES, list), "ENABLED_FEATURES should be a list"
        assert len(ENABLED_FEATURES) > 0, "ENABLED_FEATURES should not be empty"
        
        # Basic features should always be present
        assert "basic" in ENABLED_FEATURES, "Basic features should always be enabled"
        assert "preview" in ENABLED_FEATURES, "Preview features should always be enabled"
        
        if VERSION_TYPE == "free":
            # Free version should have limited features - only basic and preview
            expected_free_features = ["basic", "preview"]
            for feature in ENABLED_FEATURES:
                assert feature in expected_free_features, f"Free version should only have basic features, found '{feature}'"
        else:
            # Full version should have additional features beyond basic and preview
            assert len(ENABLED_FEATURES) > 2, "Full version should have more than just basic and preview features"
    
    def test_get_version_limits_function(self):
        """Test get_version_limits() returns correct technical limits."""
        from src.utils.constants import get_version_limits, VERSION_TYPE
        
        limits = get_version_limits()
        assert isinstance(limits, dict), "get_version_limits() should return a dictionary"
        
        # Check required keys
        required_keys = ["max_concurrent_operations"]
        for key in required_keys:
            assert key in limits, f"Missing required key '{key}' in version limits"
        assert "max_texture_size" not in limits, "Texture size limit should not be enforced"
        
        # Check value types
        assert isinstance(limits["max_concurrent_operations"], int), "max_concurrent_operations should be an integer"
        
        # Check version-specific limits
        if VERSION_TYPE == "free":
            assert limits["max_concurrent_operations"] == 1, f"Free version should have 1 concurrent operation, got {limits['max_concurrent_operations']}"
        else:
            assert limits["max_concurrent_operations"] == 4, f"Full version should have 4 concurrent operations, got {limits['max_concurrent_operations']}"

    def test_get_version_limits_full_returns_pro_limits(self):
        """Verify full version returns correct limits for concurrent operations."""
        from src.utils.constants import get_version_limits
        from unittest.mock import patch
        
        with patch('src.utils.constants.VERSION_TYPE', 'full'):
            limits = get_version_limits()
            
            assert "max_texture_size" not in limits, "Full version should not enforce a texture size limit"
            assert limits["max_concurrent_operations"] == 4, \
                f"Expected full version max_concurrent_operations=4, got {limits['max_concurrent_operations']}"

    def test_get_version_limits_free_returns_restricted_limits(self):
        """Verify free version returns restricted limits for concurrent operations only."""
        from src.utils.constants import get_version_limits
        from unittest.mock import patch
        
        with patch('src.utils.constants.VERSION_TYPE', 'free'):
            limits = get_version_limits()
            
            assert "max_texture_size" not in limits, "Free version should not enforce a texture size limit"
            assert limits["max_concurrent_operations"] == 1, \
                f"Expected free version max_concurrent_operations=1, got {limits['max_concurrent_operations']}"

    def test_has_text_fitting_returns_correct_value_per_version(self):
        """Test that has_text_fitting() returns correct value based on VERSION_TYPE."""
        from src.utils.constants import has_text_fitting
        from unittest.mock import patch
        
        # Test free version - need to patch ENABLED_FEATURES since it's computed at import
        with patch('src.utils.constants.VERSION_TYPE', 'free'), \
             patch('src.utils.constants.ENABLED_FEATURES', ['basic', 'preview']):
            assert has_text_fitting() is False
        
        # Test full version - need to patch ENABLED_FEATURES since it's computed at import
        with patch('src.utils.constants.VERSION_TYPE', 'full'), \
             patch('src.utils.constants.ENABLED_FEATURES', ['basic', 'preview', 'text_fitting']):
            assert has_text_fitting() is True



class TestRuntimeImportDetection:
    """Test suite for runtime import detection flags."""
    
    def test_presets_available_flag(self):
        """Test PRESETS_AVAILABLE flag is properly set based on import success."""
        from src import PRESETS_AVAILABLE
        assert isinstance(PRESETS_AVAILABLE, bool), "PRESETS_AVAILABLE should be a boolean"
    
    def test_utility_operators_available_flag(self):
        """Test UTILITY_OPERATORS_AVAILABLE flag is properly set based on import success."""
        from src import UTILITY_OPERATORS_AVAILABLE
        assert isinstance(UTILITY_OPERATORS_AVAILABLE, bool), "UTILITY_OPERATORS_AVAILABLE should be a boolean"


class TestFeatureAvailability:
    """Test suite for feature availability and gating."""
    
    def test_feature_gating_based_on_version(self):
        """Test that features are properly gated based on version type."""
        from src.utils.constants import is_free_version, ENABLED_FEATURES
        
        if is_free_version():
            # Free version should only have basic and preview features
            expected_features = ["basic", "preview"]
            assert set(ENABLED_FEATURES) == set(expected_features), f"Free version should only have {expected_features}"
        else:
            # Full version should have more features
            assert len(ENABLED_FEATURES) > 2, "Full version should have more than just basic features"
            assert "basic" in ENABLED_FEATURES, "Full version should include basic features"
            assert "preview" in ENABLED_FEATURES, "Full version should include preview features"
    
    def test_runtime_import_detection_flags_exist(self):
        """Test that runtime import detection flags exist."""
        try:
            from src import PRESETS_AVAILABLE, UTILITY_OPERATORS_AVAILABLE
            assert isinstance(PRESETS_AVAILABLE, bool), "PRESETS_AVAILABLE should be a boolean"
            assert isinstance(UTILITY_OPERATORS_AVAILABLE, bool), "UTILITY_OPERATORS_AVAILABLE should be a boolean"
        except ImportError as e:
            pytest.fail(f"Runtime detection flags should be available: {e}")


class TestUIComponents:
    """Test suite for UI component version display."""
    
    def test_get_version_badge_text(self):
        """Test get_version_badge_text() returns appropriate badge text."""
        from src.utils.constants import get_version_badge_text, is_free_version
        
        badge_text = get_version_badge_text()
        assert isinstance(badge_text, str), "get_version_badge_text() should return a string"
        assert len(badge_text) > 0, "Badge text should not be empty"
        
        if is_free_version():
            assert "FREE" in badge_text.upper(), "Free version badge should contain 'FREE'"
        else:
            assert "PRO" in badge_text.upper() or "FULL" in badge_text.upper(), "Full version badge should contain 'PRO' or 'FULL'"
    
    def test_should_show_feature_lock(self):
        """Test should_show_feature_lock() returns correct values for features."""
        from src.utils.constants import should_show_feature_lock, is_free_version
        
        # Test premium features from the actual implementation
        premium_features = ["presets", "utility_operators", "image_overlays", "batch_processing", "advanced_positioning"]
        for feature in premium_features:
            result = should_show_feature_lock(feature)
            assert isinstance(result, bool), f"should_show_feature_lock('{feature}') should return boolean"
            
            if is_free_version():
                assert result == True, f"Feature lock should be shown for '{feature}' in free version"
            else:
                assert result == False, f"Feature lock should not be shown for '{feature}' in full version"
    
    def test_get_upgrade_hint_text(self):
        """Test get_upgrade_hint_text() returns appropriate upgrade messages."""
        from src.utils.constants import get_upgrade_hint_text, is_free_version
        
        # The function requires a feature_name parameter
        feature_name = "Test Feature"
        hint_text = get_upgrade_hint_text(feature_name)
        assert isinstance(hint_text, str), "get_upgrade_hint_text() should return a string"
        
        if is_free_version():
            assert len(hint_text) > 0, "Free version should have upgrade hint text"
            assert feature_name in hint_text, "Upgrade hint should mention the feature name"
            assert "Pro" in hint_text, "Upgrade hint should mention Pro version"
        else:
            assert len(hint_text) == 0, "Full version should have empty upgrade hint text"
    
    def test_get_version_info_details(self):
        """Test get_version_info_details() returns comprehensive version information."""
        from src.utils.constants import get_version_info_details, is_free_version, get_version_limits
        
        info_details = get_version_info_details()
        assert isinstance(info_details, dict), "get_version_info_details() should return a dictionary"
        assert len(info_details) > 0, "Version info details should not be empty"


class TestIntegrationScenarios:
    """Test suite for cross-system integration validation."""
    
    def test_template_and_runtime_consistency(self):
        """Test that template-generated constants and runtime flags are consistent."""
        from src.utils.constants import is_free_version, ENABLED_FEATURES
        from src import PRESETS_AVAILABLE, UTILITY_OPERATORS_AVAILABLE
        
        # In a properly built system, runtime availability should align with template configuration
        if is_free_version():
            # Free version should have limited features in template
            expected_features = ["basic", "preview"]
            assert set(ENABLED_FEATURES) == set(expected_features), f"Template should only enable basic features in free version, got {ENABLED_FEATURES}"
        else:
            # Full version should have more features enabled in template
            assert len(ENABLED_FEATURES) > 2, "Template should enable more features in full version"
            assert "basic" in ENABLED_FEATURES, "Template should enable basic features in full version"
            assert "preview" in ENABLED_FEATURES, "Template should enable preview features in full version"
    
    def test_mock_operators_dont_crash(self):
        """Test that mock operators are properly implemented and don't crash."""
        # This test ensures that when premium features are missing,
        # the system gracefully handles it with mock implementations
        
        # Test that we can import the main module without crashes
        try:
            import src
            assert True, "Main module import should not crash"
        except Exception as e:
            pytest.fail(f"Main module import crashed: {e}")
        
        # Test that runtime flags are properly set
        assert hasattr(src, 'PRESETS_AVAILABLE'), "Runtime should set PRESETS_AVAILABLE flag"
        assert hasattr(src, 'UTILITY_OPERATORS_AVAILABLE'), "Runtime should set UTILITY_OPERATORS_AVAILABLE flag"


class TestVersionDifferentiationScenarios:
    """Test specific free vs full version difference scenarios."""
    
    def test_free_version_complete_scenario(self):
        """Test complete free version scenario with all restrictions."""
        from src.utils.constants import is_free_version, get_version_limits, ENABLED_FEATURES
        
        if is_free_version():
            # Feature restrictions - free version should only have basic features
            expected_features = ["basic", "preview"]
            assert set(ENABLED_FEATURES) == set(expected_features), f"Free version should only have {expected_features}"
            
            # Technical limitations
            limits = get_version_limits()
            assert "max_texture_size" not in limits, "Free version should not enforce a texture size cap"
            assert limits["max_concurrent_operations"] == 1, "Should have 1 concurrent operation limit"
    
    def test_full_version_complete_scenario(self):
        """Test complete full version scenario with all features enabled."""
        from src.utils.constants import is_free_version, is_full_version, get_version_limits, ENABLED_FEATURES
        
        if not is_free_version():
            # Version detection
            assert is_full_version() == True, "Should detect full version"
            
            # Full version should have more features than free
            assert len(ENABLED_FEATURES) > 2, "Full version should have more than just basic features"
            assert "basic" in ENABLED_FEATURES, "Full version should include basic features"
            assert "preview" in ENABLED_FEATURES, "Full version should include preview features"
            
            # Generous technical limits
            limits = get_version_limits()
            assert "max_texture_size" not in limits, "Full version should not enforce a texture size cap"
            assert limits["max_concurrent_operations"] == 4, "Should have 4 concurrent operations limit"
