"""
Comprehensive tests for import error handling in the text texture generator addon.
Tests conditional imports, PIL handling, mock operators, and version-specific features.
"""

import sys
import pytest
import tempfile
import zipfile
import os
from unittest.mock import patch, MagicMock, Mock
import importlib


class TestConditionalImports:
    """Test that modules handle missing imports gracefully."""
    
    def test_operators_init_handles_missing_imports(self):
        """Test that operators/__init__.py sets up empty lists when modules missing."""
        # Test operators module can import and has necessary attributes
        try:
            from src.operators import PRESET_OPERATORS, UTILITY_OPERATORS
            # Should have lists (empty or populated)
            assert isinstance(PRESET_OPERATORS, list)
            assert isinstance(UTILITY_OPERATORS, list)
        except ImportError as e:
            pytest.fail(f"operators/__init__.py should import successfully: {e}")
    
    def test_main_init_has_conditional_imports(self):
        """Test that main __init__.py has the conditional import structure."""
        # Read the main __init__.py to verify it has conditional imports
        from pathlib import Path
        init_file = Path("src/__init__.py")
        with open(init_file, 'r') as f:
            content = f.read()
        
        # Should have try-catch blocks for conditional imports
        assert 'try:' in content
        assert 'except ImportError' in content
        assert 'MockOperator' in content
    
    def test_core_init_has_conditional_imports(self):
        """Test that core/__init__.py has conditional import structure."""
        # Test core module can import
        try:
            import src.core
            # Should have the normal maps function available (real or mock)
            assert hasattr(src.core, 'generate_normal_map_from_alpha')
            assert callable(src.core.generate_normal_map_from_alpha)
            # Should have the availability flag
            assert hasattr(src.core, 'NORMAL_MAPS_AVAILABLE')
            assert isinstance(src.core.NORMAL_MAPS_AVAILABLE, bool)
        except ImportError as e:
            pytest.fail(f"core/__init__.py should import successfully: {e}")


class TestPILImportHandling:
    """Test that PIL imports are handled gracefully when PIL is not available."""
    
    def test_normal_maps_pil_handling(self):
        """Test that normal_maps.py has PIL handling structure."""
        # Simply test that normal_maps can be imported
        try:
            from src.core import normal_maps
            # Should have some indication of PIL handling
            assert hasattr(normal_maps, 'PIL_AVAILABLE') or hasattr(normal_maps, 'generate_normal_map_from_alpha')
        except ImportError as e:
            pytest.fail(f"normal_maps.py should handle PIL gracefully: {e}")
    
    def test_ui_preview_handles_missing_pil(self):
        """Test that ui/preview.py handles missing PIL gracefully."""
        try:
            from src.ui import preview
            # Should import successfully with PIL handling
            assert hasattr(preview, 'PIL_AVAILABLE')
            assert isinstance(preview.PIL_AVAILABLE, bool)
        except ImportError as e:
            pytest.fail(f"ui/preview.py should handle missing PIL gracefully: {e}")
    
    def test_generation_engine_imports_successfully(self):
        """Test that generation_engine.py imports successfully."""
        try:
            from src.core import generation_engine
            # Should import successfully and have main functions
            assert hasattr(generation_engine, 'generate_texture_image')
        except ImportError as e:
            pytest.fail(f"generation_engine.py should import successfully: {e}")


class TestMockOperators:
    """Test that mock operators work correctly in free version."""
    
    def test_mock_operator_exists_in_main_init(self):
        """Test that MockOperator is defined in main __init__.py."""
        # Read the main __init__.py to verify MockOperator is defined
        from pathlib import Path
        init_file = Path("src/__init__.py")
        with open(init_file, 'r') as f:
            content = f.read()
        
        # Should have MockOperator class definition
        assert 'class MockOperator' in content
        assert 'bl_idname' in content
        assert 'bl_label' in content
        assert 'execute' in content
    
    def test_mock_operators_structure_in_main_init(self):
        """Test that mock operators are properly structured in main __init__.py."""
        # Read the main __init__.py to verify conditional operator assignments
        from pathlib import Path
        init_file = Path("src/__init__.py")
        with open(init_file, 'r') as f:
            content = f.read()
        
        # Should have conditional operator assignments
        operator_names = [
            'TEXT_TEXTURE_OT_save_preset',
            'TEXT_TEXTURE_OT_load_preset',
            'TEXT_TEXTURE_OT_delete_preset'
        ]
        
        for op_name in operator_names:
            assert op_name in content, f"Should reference {op_name} in __init__.py"


class TestVersionSpecificConstants:
    """Test that version-specific constants are set correctly."""
    
    def test_constants_has_enabled_features(self):
        """Test that constants.py includes ENABLED_FEATURES."""
        from src.utils import constants
        
        assert hasattr(constants, 'ENABLED_FEATURES')
        assert isinstance(constants.ENABLED_FEATURES, list)
        assert len(constants.ENABLED_FEATURES) > 0
    
    def test_constants_has_version_type(self):
        """Test that constants.py includes VERSION_TYPE."""
        from src.utils import constants
        
        assert hasattr(constants, 'VERSION_TYPE')
        assert constants.VERSION_TYPE in ['free', 'full']
    
    def test_version_helper_functions(self):
        """Test that version helper functions work correctly."""
        from src.utils import constants
        
        assert hasattr(constants, 'is_free_version')
        assert hasattr(constants, 'is_full_version')
        assert hasattr(constants, 'get_version_limits')
        
        # Functions should return appropriate types
        assert isinstance(constants.is_free_version(), bool)
        assert isinstance(constants.is_full_version(), bool)
        assert isinstance(constants.get_version_limits(), dict)


class TestPackageIntegrity:
    """Test that built packages have correct structure and no import issues."""
    
    def test_free_package_excludes_correct_files(self):
        """Test that free version package excludes the right files."""
        from pathlib import Path
        free_package = Path("dist/text_texture_generator_v1.0.0_free.zip")
        if not free_package.exists():
            pytest.skip("Free package not found - run build first")
        
        with zipfile.ZipFile(free_package, 'r') as zip_file:
            file_list = zip_file.namelist()
            
            # Files that should be excluded from free version
            excluded_files = [
                'operators/preset_ops.py',
                'operators/utility_ops.py', 
                'core/normal_maps.py'
            ]
            
            for excluded_file in excluded_files:
                matching_files = [f for f in file_list if excluded_file in f]
                assert len(matching_files) == 0, f"Free version should not contain {excluded_file}"
    
    def test_full_package_includes_all_files(self):
        """Test that full version package includes all files."""
        from pathlib import Path
        full_package = Path("dist/text_texture_generator_v1.0.0.zip")
        if not full_package.exists():
            pytest.skip("Full package not found - run build first")
        
        with zipfile.ZipFile(full_package, 'r') as zip_file:
            file_list = zip_file.namelist()
            
            # Files that should be included in full version
            required_files = [
                'operators/preset_ops.py',
                'operators/utility_ops.py',
                'core/normal_maps.py'
            ]
            
            for required_file in required_files:
                matching_files = [f for f in file_list if required_file in f]
                assert len(matching_files) > 0, f"Full version should contain {required_file}"
    
    def test_constants_contains_enabled_features_in_packages(self):
        """Test that both packages have constants.py with ENABLED_FEATURES."""
        from pathlib import Path
        
        packages = [
            ("dist/text_texture_generator_v1.0.0_free.zip", "Free"),
            ("dist/text_texture_generator_v1.0.0.zip", "Full")
        ]
        
        for package_path, package_type in packages:
            package = Path(package_path)
            if not package.exists():
                continue  # Skip if package doesn't exist
            
            with zipfile.ZipFile(package, 'r') as zip_file:
                file_list = zip_file.namelist()
                constants_files = [f for f in file_list if 'utils/constants.py' in f]
                assert len(constants_files) > 0, f"{package_type} package should contain constants.py"
                
                # Read constants file and check for ENABLED_FEATURES
                constants_file = constants_files[0]
                constants_content = zip_file.read(constants_file).decode('utf-8')
                assert 'ENABLED_FEATURES' in constants_content, f"{package_type} package constants.py should contain ENABLED_FEATURES"


class TestBuildSystemRobustness:
    """Test that the build system handles edge cases properly."""
    
    def test_build_system_handles_missing_git_tags(self):
        """Test that build system works even without git tags."""
        from build.sync_version import get_latest_git_tag
        
        # Should return a version or None (both are acceptable)
        version = get_latest_git_tag()
        # Either a valid version string or None is acceptable
        if version is not None:
            assert isinstance(version, str)
            assert len(version) > 0
    
    def test_template_system_has_all_required_variables(self):
        """Test that template system includes all required variables."""
        from build.sync_version import create_template_variables, load_config
        
        config = load_config()
        variables = create_template_variables(config, "1.0.0", "full")
        
        required_vars = [
            'VERSION',
            'VERSION_TYPE',
            'ENABLED_FEATURES'
        ]
        
        for var in required_vars:
            assert var in variables, f"Template variables should include {var}"