"""
Unit tests for modal text editor operator.

Tests verify:
- Operator class exists and is properly structured
- PRO-only access control via poll()
- Text processing and limit enforcement
- Proper Blender operator contract
"""

import pytest
from unittest.mock import Mock, MagicMock, patch


class TestModalTextEditorOperator:
    """Test suite for TEXT_TEXTURE_OT_edit_text operator."""

    def test_operator_class_exists(self):
        """Operator class must be importable and follow Blender conventions."""
        from src.operators.text_editor_ops import TEXT_TEXTURE_OT_edit_text
        
        assert hasattr(TEXT_TEXTURE_OT_edit_text, 'bl_idname')
        assert TEXT_TEXTURE_OT_edit_text.bl_idname == "text_texture.edit_text"
        assert hasattr(TEXT_TEXTURE_OT_edit_text, 'bl_label')
        assert hasattr(TEXT_TEXTURE_OT_edit_text, 'poll')
        assert hasattr(TEXT_TEXTURE_OT_edit_text, 'invoke')
        assert hasattr(TEXT_TEXTURE_OT_edit_text, 'execute')
        assert hasattr(TEXT_TEXTURE_OT_edit_text, 'draw')

    def test_poll_denies_access_in_free_version(self):
        """poll() must return False when running in the free version."""
        from src.operators.text_editor_ops import TEXT_TEXTURE_OT_edit_text
        
        mock_context = Mock()
        
        with patch('src.operators.text_editor_ops.is_full_version', return_value=False):
            result = TEXT_TEXTURE_OT_edit_text.poll(mock_context)
            assert result is False, "FREE version should not have access to text editor"

    def test_poll_allows_access_in_pro_version(self):
        """poll() must return True when running in the pro version."""
        from src.operators.text_editor_ops import TEXT_TEXTURE_OT_edit_text
        
        mock_context = Mock()
        
        with patch('src.operators.text_editor_ops.is_full_version', return_value=True):
            result = TEXT_TEXTURE_OT_edit_text.poll(mock_context)
            assert result is True, "PRO version should have access to text editor"

    def test_invoke_copies_current_text_to_temp(self):
        """invoke() must copy scene text property to temp_text for editing."""
        from src.operators.text_editor_ops import TEXT_TEXTURE_OT_edit_text
        
        operator = TEXT_TEXTURE_OT_edit_text()
        mock_context = Mock()
        mock_context.scene.text_texture_props.text = "Test text"
        mock_context.window_manager.invoke_props_dialog.return_value = {'RUNNING_MODAL'}
        mock_event = Mock()
        
        result = operator.invoke(mock_context, mock_event)
        
        assert operator.temp_text == "Test text"
        assert result == {'RUNNING_MODAL'}
        mock_context.window_manager.invoke_props_dialog.assert_called_once()

    def test_execute_saves_temp_text_back_to_property(self):
        """execute() must save edited temp_text back to scene property."""
        from src.operators.text_editor_ops import TEXT_TEXTURE_OT_edit_text
        
        operator = TEXT_TEXTURE_OT_edit_text()
        operator.temp_text = "Edited text"
        
        mock_context = Mock()
        mock_context.scene.text_texture_props.text = "Old text"
        
        result = operator.execute(mock_context)
        
        assert result == {'FINISHED'}
        assert mock_context.scene.text_texture_props.text == "Edited text"

    def test_execute_enforces_character_limit(self):
        """execute() must truncate text exceeding max_text_length."""
        from src.operators.text_editor_ops import TEXT_TEXTURE_OT_edit_text
        
        operator = TEXT_TEXTURE_OT_edit_text()
        # Create text exceeding 4096 char limit
        operator.temp_text = "x" * 5000
        
        mock_context = Mock()
        mock_context.scene.text_texture_props.text = ""
        
        operator.execute(mock_context)
        
        saved_text = mock_context.scene.text_texture_props.text
        assert len(saved_text) == 4096, f"Expected 4096 chars, got {len(saved_text)}"

    def test_operator_has_temp_text_property(self):
        """Operator must have StringProperty named temp_text."""
        from src.operators.text_editor_ops import TEXT_TEXTURE_OT_edit_text
        
        operator = TEXT_TEXTURE_OT_edit_text()
        # Blender properties are accessible as attributes
        assert hasattr(operator, 'temp_text')
        # Should be able to set and get
        operator.temp_text = "Test content"
        assert operator.temp_text == "Test content"

    def test_operator_registration_list_exists(self):
        """Module must expose classes tuple for Blender registration."""
        from src.operators import text_editor_ops
        
        assert hasattr(text_editor_ops, 'classes')
        assert isinstance(text_editor_ops.classes, tuple)
        assert len(text_editor_ops.classes) > 0

    def test_operator_module_has_register_function(self):
        """Module must have register() function for Blender."""
        from src.operators import text_editor_ops
        
        assert hasattr(text_editor_ops, 'register')
        assert callable(text_editor_ops.register)

    def test_operator_module_has_unregister_function(self):
        """Module must have unregister() function for Blender."""
        from src.operators import text_editor_ops
        
        assert hasattr(text_editor_ops, 'unregister')
        assert callable(text_editor_ops.unregister)
