"""
Text Texture Generator - Utility Operators
Handles preview refresh, font refresh, UI operations, overlay management, and positioning utilities.
"""

import bpy
from bpy.types import Operator
from bpy.props import StringProperty, IntProperty, EnumProperty
import os

# Import functions from parent module
try:
    pass
    
    # First, let's see what's actually available in ui.preview
    from text_texture_generator import ui
    
    # Now try the actual import that's failing
    from .generation_engine import generate_preview
    from ..utils.system import get_system_fonts, get_font_enum_items
    from .storage_system import refresh_presets_sync, ensure_presets_available
    from ..utils.constants import sync_margin_values
except ImportError as e:
    pass
    
    # Let's check if it's available in core.generation_engine
    try:
        pass
        from .generation_engine import generate_preview
        from ..utils.system import get_system_fonts, get_font_enum_items
        from .storage_system import refresh_presets_sync, ensure_presets_available
        from ..utils.constants import sync_margin_values
    except ImportError as fallback_error:
        pass
        # Fallback imports for development/testing
    def generate_preview(context):
        pass
        print("Fallback generate_preview called")
        return None
    def get_system_fonts():
        pass
        return {}
    def get_font_enum_items():
        pass
        return [("default", "Default Font", "Use system default font", 0)]
    def refresh_presets_sync():
        pass
        return True
    def ensure_presets_available():
        pass
        return True
    def sync_margin_values(props, changed_margin):
        pass
        pass


class TEXT_TEXTURE_OT_refresh_preview(Operator):
    pass
    """Force refresh the preview"""
    bl_idname = "text_texture.refresh_preview"
    bl_label = "Refresh Preview"
    bl_description = "Force refresh the preview image"
    bl_options = {'REGISTER', 'UNDO'}
    
    def execute(self, context):
        pass
        props = context.scene.text_texture_props
        
        # Clear existing preview first
        props.preview_image = None
        
        # Generate new preview
        result = generate_preview(context)
        
        if result:
            pass
            self.report({'INFO'}, f"Preview refreshed at {props.preview_size}px")
        else:
            pass
            self.report({'ERROR'}, "Failed to generate preview - check console for details")
        
        # Force UI update
        for area in context.screen.areas:
            pass
            area.tag_redraw()
        
        return {'FINISHED'}


class TEXT_TEXTURE_OT_view_preview_zoom(Operator):
    pass
    """Open preview in new Image Editor window with zoom support"""
    bl_idname = "text_texture.view_preview_zoom"
    bl_label = "Enable Zoom"
    bl_description = "Open preview in new Image Editor window with zoom and pan controls"
    bl_options = {'REGISTER', 'UNDO'}
    
    def execute(self, context):
        pass
        props = context.scene.text_texture_props
        
        # Generate preview image when button is clicked
        result = generate_preview(context)
        
        if not result:
            pass
            self.report({'ERROR'}, "Failed to generate preview")
            return {'CANCELLED'}
        
        if not props.preview_image:
            pass
            self.report({'ERROR'}, "No preview image to display")
            return {'CANCELLED'}
        
        # Open a new window with Image Editor
        
        try:
            pass
            # Create a new window
            bpy.ops.screen.userpref_show('INVOKE_DEFAULT')
            
            # Wait a moment and then change the newly opened window to Image Editor
            def setup_image_window():
                pass
                # Find the newest window (should be the one we just opened)
                newest_window = None
                for window in bpy.context.window_manager.windows:
                    pass
                    if window.screen.name.startswith("temp"):
                        pass
                        newest_window = window
                        break
                
                if not newest_window:
                    pass
                    # Fallback: use any non-main window
                    for window in bpy.context.window_manager.windows:
                        pass
                        if window != bpy.context.window:
                            pass
                            newest_window = window
                            break
                
                if newest_window:
                    pass
                    # Set the area type to Image Editor
                    for area in newest_window.screen.areas:
                        pass
                        if area.type == 'PREFERENCES':
                            pass
                            area.type = 'IMAGE_EDITOR'
                            
                            # Set the preview image
                            for space in area.spaces:
                                pass
                                if space.type == 'IMAGE_EDITOR':
                                    pass
                                    space.image = props.preview_image
                                    
                                    # Set up proper viewing
                                    override = {
                                        'window': newest_window,
                                        'screen': newest_window.screen,
                                        'area': area,
                                        'region': area.regions[0] if area.regions else None
                                    }
                                    
                                    with bpy.context.temp_override(**override):
                                        try:
                                            pass
                                            bpy.ops.image.view_all(fit_view=True)
                                        except Exception as e:
                                            pass
                                    
                                    break
                            break
                    
                    self.report({'INFO'}, "✅ NEW WINDOW OPENED! Use mouse wheel to zoom, middle-mouse to pan")
                else:
                    pass
                    self.report({'ERROR'}, "Failed to setup new window")
                
                return None  # Stop timer
            
            # Use a timer to set up the window after it opens
            bpy.app.timers.register(setup_image_window, first_interval=0.1)
            
        except Exception as e:
            pass
            # Fallback to old behavior if new window creation fails
            self.report({'WARNING'}, "New window failed, trying area split instead")
            
            # Find any area to split
            for area in context.screen.areas:
                pass
                if area.type in ['NODE_EDITOR', 'VIEW_3D', 'PROPERTIES']:
                    pass
                    
                    # Split horizontally to create a new area
                    with context.temp_override(area=area):
                        bpy.ops.screen.area_split(direction='HORIZONTAL', factor=0.6)
                    
                    # Find the newly created area
                    for new_area in context.screen.areas:
                        pass
                        if new_area != area and new_area.y != area.y:
                            pass
                            new_area.type = 'IMAGE_EDITOR'
                            
                            # Set the image in the Image Editor
                            for space in new_area.spaces:
                                pass
                                if space.type == 'IMAGE_EDITOR':
                                    pass
                                    space.image = props.preview_image
                                    break
                            
                            # Tag for redraw and fit to view
                            new_area.tag_redraw()
                            override = context.copy()
                            override['area'] = new_area
                            override['region'] = new_area.regions[0]
                            
                            with context.temp_override(**override):
                                try:
                                    pass
                                    bpy.ops.image.view_all(fit_view=True)
                                except Exception as e:
                                    pass
                            
                            self.report({'INFO'}, "✅ ZOOM ENABLED! Use mouse wheel to zoom, middle-mouse to pan")
                            return {'FINISHED'}
                    break
            
            self.report({'ERROR'}, "Failed to create Image Editor")
            return {'CANCELLED'}
        
        return {'FINISHED'}


class TEXT_TEXTURE_OT_open_panel(Operator):
    pass
    """Open Text Texture Generator panel"""
    bl_idname = "text_texture.open_panel"
    bl_label = "Open Text Texture Panel"
    bl_description = "Open the Text Texture Generator panel in the sidebar"
    bl_options = {'REGISTER', 'UNDO'}
    
    def execute(self, context):
        pass
        # Ensure the sidebar is visible
        for area in context.screen.areas:
            pass
            if area.type == 'VIEW_3D':
                pass
                for space in area.spaces:
                    pass
                    if space.type == 'VIEW_3D':
                        pass
                        space.show_region_ui = True
                        # Switch to Tool tab
                        area.tag_redraw()
                        self.report({'INFO'}, "Text Texture panel opened in 3D View sidebar (press N if not visible)")
                        return {'FINISHED'}
            elif area.type == 'NODE_EDITOR':
                for space in area.spaces:
                    pass
                    if space.type == 'NODE_EDITOR':
                        pass
                        space.show_region_ui = True
                        area.tag_redraw()
                        self.report({'INFO'}, "Text Texture panel opened in Shader Editor sidebar")
                        return {'FINISHED'}
        
        self.report({'WARNING'}, "Please open a 3D View or Shader Editor first")
        return {'CANCELLED'}


class TEXT_TEXTURE_OT_refresh_fonts(Operator):
    pass
    """Refresh fonts"""
    bl_idname = "text_texture.refresh_fonts"
    bl_label = "Refresh Fonts"
    bl_description = "Refresh font list"
    bl_options = {'REGISTER', 'UNDO'}
    
    def execute(self, context):
        pass
        if hasattr(get_font_enum_items, 'cached_fonts'):
            pass
            del get_font_enum_items.cached_fonts
        get_font_enum_items.cached_fonts = get_system_fonts()
        self.report({'INFO'}, f"Found {len(get_font_enum_items.cached_fonts)} fonts")
        return {'FINISHED'}


class TEXT_TEXTURE_OT_refresh_presets(Operator):
    pass
    """Refresh presets from blend file and local storage"""
    bl_idname = "text_texture.refresh_presets"
    bl_label = "Refresh Presets"
    bl_description = "Reload presets from blend file and local storage"
    bl_options = {'REGISTER', 'UNDO'}
    
    def execute(self, context):
        pass
        try:
            pass
            # Use the reliable synchronous refresh system
            success = refresh_presets_sync()
            
            if success:
                pass
                props = context.scene.text_texture_props
                total_presets = len(props.presets)
                
                # Count by source for detailed reporting
                blend_count = len([p for p in props.presets if p.source == 'BLEND_FILE'])
                persistent_count = len([p for p in props.presets if p.source == 'PERSISTENT_FILE'])
                local_count = len([p for p in props.presets if p.source == 'LOCAL_FILE'])
                
                self.report({'INFO'}, f"✅ Refreshed {total_presets} presets ({blend_count} blend file, {persistent_count} persistent, {local_count} local)")
            else:
                pass
                self.report({'WARNING'}, "Preset refresh completed with issues - check console for details")
            
            # Force UI redraw
            for area in context.screen.areas:
                pass
                area.tag_redraw()
            
            return {'FINISHED'}
            
        except Exception as e:
            pass
            self.report({'ERROR'}, f"Failed to refresh presets: {str(e)}")
            import traceback
            traceback.print_exc()
            return {'CANCELLED'}


class TEXT_TEXTURE_OT_add_overlay(Operator):
    pass
    """Add new composition component"""
    bl_idname = "text_texture.add_overlay"
    bl_label = "Add Component"
    bl_description = "Add new composition component"
    bl_options = {'REGISTER', 'UNDO'}

    placement_mode: EnumProperty(
        name="Placement Mode",
        items=[
            ('ABSOLUTE', "Absolute", ""),
            ('PREPEND', "Prepend", ""),
            ('APPEND', "Append", "")
        ],
        default='ABSOLUTE'
    )
    
    def execute(self, context):
        print(f"DEBUG ENTRY: TEXT_TEXTURE_OT_add_overlay.execute (mode: {self.placement_mode})")
        props = context.scene.text_texture_props
        
        overlay = props.image_overlays.add()
        overlay.name = f"Component {len(props.image_overlays)}"
        overlay.placement_mode = self.placement_mode
        overlay.component_type = 'TEXT' if self.placement_mode in {'PREPEND', 'APPEND'} else 'IMAGE'
        props.active_overlay_index = len(props.image_overlays) - 1
        
        print(f"DEBUG EXIT: TEXT_TEXTURE_OT_add_overlay.execute - Created: '{overlay.name}', New Total: {len(props.image_overlays)}")
        
        # Force UI redraw
        for area in context.screen.areas:
            area.tag_redraw()
        
        self.report({'INFO'}, f"Added component: {overlay.name}")
        return {'FINISHED'}


class TEXT_TEXTURE_OT_remove_overlay(Operator):
    pass
    """Remove active image overlay"""
    bl_idname = "text_texture.remove_overlay"
    bl_label = "Remove Overlay"
    bl_description = "Remove active image overlay"
    bl_options = {'REGISTER', 'UNDO'}
    
    def execute(self, context):
        pass
        props = context.scene.text_texture_props
        
        if props.image_overlays and props.active_overlay_index < len(props.image_overlays):
            pass
            overlay_name = props.image_overlays[props.active_overlay_index].name
            props.image_overlays.remove(props.active_overlay_index)
            
            # Update active index
            if props.active_overlay_index >= len(props.image_overlays) and props.image_overlays:
                pass
                props.active_overlay_index = len(props.image_overlays) - 1
            
            # Force UI redraw
            for area in context.screen.areas:
                pass
                area.tag_redraw()
            
            self.report({'INFO'}, f"Removed overlay: {overlay_name}")
        else:
            pass
            self.report({'WARNING'}, "No overlay to remove")
        
        return {'FINISHED'}


class TEXT_TEXTURE_OT_set_anchor_point(Operator):
    pass
    """Set anchor point for text positioning"""
    bl_idname = "text_texture.set_anchor_point"
    bl_label = "Set Anchor Point"
    bl_description = "Set text anchor position"
    bl_options = {'REGISTER', 'UNDO'}
    
    anchor_point: StringProperty()
    
    def execute(self, context):
        pass
        props = context.scene.text_texture_props
        props.anchor_point = self.anchor_point
        return {'FINISHED'}


class TEXT_TEXTURE_OT_sync_margins(Operator):
    pass
    """Sync margin values when linked"""
    bl_idname = "text_texture.sync_margins"
    bl_label = "Sync Margins"
    bl_description = "Synchronize margin values"
    bl_options = {'REGISTER', 'UNDO'}
    
    margin_type: StringProperty()
    
    def execute(self, context):
        pass
        props = context.scene.text_texture_props
        sync_margin_values(props, self.margin_type)
        return {'FINISHED'}


class TEXT_TEXTURE_OT_duplicate_overlay(Operator):
    pass
    """Duplicate a composition component"""
    bl_idname = "text_texture.duplicate_overlay"
    bl_label = "Duplicate Component"
    bl_description = "Duplicate this composition component"
    bl_options = {'REGISTER', 'UNDO'}
    
    overlay_index: IntProperty()
    
    def execute(self, context):
        pass
        props = context.scene.text_texture_props
        
        if 0 <= self.overlay_index < len(props.image_overlays):
            pass
            source_overlay = props.image_overlays[self.overlay_index]
            
            # Debug logging
            
            new_overlay = props.image_overlays.add()
            
            # Copy all properties with explicit verification
            new_overlay.name = f"{source_overlay.name} Copy"
            new_overlay.component_type = source_overlay.component_type
            new_overlay.image_path = source_overlay.image_path
            new_overlay.text_content = source_overlay.text_content
            new_overlay.x_position = source_overlay.x_position
            new_overlay.y_position = source_overlay.y_position
            new_overlay.scale = source_overlay.scale
            new_overlay.rotation = source_overlay.rotation
            # Fix z-index assignment for duplicated overlays to ensure proper visibility
            # For PREPEND/APPEND overlays, increment z_index to ensure duplicate appears above original
            # This prevents the duplicate from being rendered behind the original overlay
            if source_overlay.placement_mode in ['PREPEND', 'APPEND']:
                pass
                # Increment z_index to ensure proper layering order for duplicated overlay
                new_overlay.z_index = min(source_overlay.z_index + 1, 10)  # Cap at max z_index value
            else:
                pass
                # For ABSOLUTE overlays, keep same z_index (different positions so no overlap issue)
                new_overlay.z_index = source_overlay.z_index
            new_overlay.placement_mode = source_overlay.placement_mode
            new_overlay.text_spacing = source_overlay.text_spacing
            new_overlay.image_spacing = source_overlay.image_spacing
            new_overlay.enabled = source_overlay.enabled
            
            # Verify the copy was successful
            
            # Move to position after source
            new_index = len(props.image_overlays) - 1
            target_index = min(self.overlay_index + 1, new_index)
            
            if new_index != target_index:
                pass
                props.image_overlays.move(new_index, target_index)
            
            props.active_overlay_index = target_index
            
            # Clear any cached images to force reload
            
            # Set the updating flag to prevent recursive updates
            props.is_updating = True
            
            try:
                pass
                # Force immediate preview regeneration
                preview_result = generate_preview(context)
                if preview_result:
                    pass
                else:
                    pass
                
                # Force UI redraw
                for area in context.screen.areas:
                    pass
                    area.tag_redraw()
                    
            except Exception as e:
                pass
                import traceback
                traceback.print_exc()
            finally:
                props.is_updating = False
            
            
            self.report({'INFO'}, f"✅ Duplicated component: {source_overlay.name}")
        else:
            pass
            self.report({'ERROR'}, "Invalid overlay index")
            return {'CANCELLED'}
        
        return {'FINISHED'}


class TEXT_TEXTURE_OT_delete_overlay(Operator):
    pass
    """Delete a composition component"""
    bl_idname = "text_texture.delete_overlay"
    bl_label = "Delete Component"
    bl_description = "Delete this composition component"
    bl_options = {'REGISTER', 'UNDO'}
    
    overlay_index: IntProperty()
    
    def execute(self, context):
        pass
        props = context.scene.text_texture_props
        
        
        if 0 <= self.overlay_index < len(props.image_overlays):
            pass
            overlay_name = props.image_overlays[self.overlay_index].name
            
            props.image_overlays.remove(self.overlay_index)
            
            # Update active index
            if props.active_overlay_index >= len(props.image_overlays) and props.image_overlays:
                pass
                props.active_overlay_index = len(props.image_overlays) - 1
            elif not props.image_overlays:
                props.active_overlay_index = 0
            
            
            # Force preview update after deletion
            try:
                pass
                generate_preview(context)
            except Exception as e:
                pass
            
            # Force UI redraw
            for area in context.screen.areas:
                pass
                area.tag_redraw()
            
            self.report({'INFO'}, f"Deleted component: {overlay_name}")
        else:
            pass
            self.report({'ERROR'}, "Invalid overlay index")
            return {'CANCELLED'}
        
        return {'FINISHED'}


class TEXT_TEXTURE_OT_move_overlay(Operator):
    pass
    """Move a composition component within its placement group"""
    bl_idname = "text_texture.move_overlay"
    bl_label = "Move Component"
    bl_description = "Move component up or down within its placement group"
    bl_options = {'REGISTER', 'UNDO'}
    
    overlay_index: IntProperty()
    direction: EnumProperty(
        items=[
            ('UP', 'Up', 'Move overlay up in list'),
            ('DOWN', 'Down', 'Move overlay down in list')
        ]
    )
    
    def execute(self, context):
        pass
        props = context.scene.text_texture_props
        
        
        if 0 <= self.overlay_index < len(props.image_overlays):
            pass
            current_index = self.overlay_index
            new_index = current_index
            target_mode = props.image_overlays[current_index].placement_mode
            
            step = -1 if self.direction == 'UP' else 1
            probe = current_index + step
            while 0 <= probe < len(props.image_overlays):
                if props.image_overlays[probe].placement_mode == target_mode:
                    new_index = probe
                    break
                probe += step
            
            if new_index != current_index:
                pass
                overlay_name = props.image_overlays[current_index].name
                props.image_overlays.move(current_index, new_index)
                props.active_overlay_index = new_index
                
                
                # Force preview update after moving (order affects rendering)
                try:
                    pass
                    generate_preview(context)
                except Exception as e:
                    pass
                
                self.report({'INFO'}, f"Moved component {self.direction.lower()}")
            else:
                pass
                self.report({'INFO'}, f"Component is already at {self.direction.lower()} edge")
        else:
            pass
            self.report({'ERROR'}, "Invalid overlay index")
            return {'CANCELLED'}
        
        return {'FINISHED'}
        
class TEXT_TEXTURE_OT_recover_data(Operator):
    """Scan and recover orphaned composition data"""
    bl_idname = "text_texture.recover_data"
    bl_label = "Scan for Lost Components"
    bl_description = "Scan current scene for orphaned composition data and attempt to re-link it"
    bl_options = {'REGISTER', 'UNDO'}
    
    quiet: bpy.props.BoolProperty(
        name="Quiet Mode",
        description="Suppress info messages when nothing is found",
        default=False
    )
    
    def execute(self, context):
        props = context.scene.text_texture_props
        print(f"DEBUG: TEXT_TEXTURE_OT_recover_data - STARTING SCAN (Quiet: {self.quiet})")
        
        # Check if the underlying collection is just empty or actually missing
        if not hasattr(props, "image_overlays"):
             if not self.quiet:
                 self.report({'ERROR'}, "Critical: image_overlays property missing from scene data")
             return {'CANCELLED'}
             
        # Run Migration for Legacy Text Fields!
        # If the user opened an old .blend file, the prepend_text is still in the Scene props,
        # but won't be seen by the new Component UI.
        legacy_prepend = props.prepend_text.strip() if props.prepend_text else ""
        legacy_append = props.append_text.strip() if props.append_text else ""
        
        migrated_count = 0
        
        if legacy_prepend:
            overlay = props.image_overlays.add()
            overlay.name = "Recovered Prefix"
            overlay.component_type = 'TEXT'
            overlay.placement_mode = 'PREPEND'
            overlay.text_content = legacy_prepend
            # Legacy margin was 0-100 where 10 = 1 space character.
            # New text_spacing is canvas percentage (0-100%).
            # We map: legacy 10 -> 2%, legacy 100 -> 20%
            margin_val = props.prepend_margin
            overlay.text_spacing = min(30.0, float(margin_val) / 5.0) if margin_val else 0.0
            overlay.enabled = True
            props.prepend_text = ""
            migrated_count += 1
            
        if legacy_append:
            overlay = props.image_overlays.add()
            overlay.name = "Recovered Suffix"
            overlay.component_type = 'TEXT'
            overlay.placement_mode = 'APPEND'
            overlay.text_content = legacy_append
            margin_val = props.append_margin
            overlay.text_spacing = min(30.0, float(margin_val) / 5.0) if margin_val else 0.0
            overlay.enabled = True
            props.append_text = ""
            migrated_count += 1
            
        total = len(props.image_overlays)
        print(f"DEBUG: Current count after recovery: {total}")
        
        # Force a tag redraw and a collection refresh
        for area in context.screen.areas:
            area.tag_redraw()
            
        if total == 0 and migrated_count == 0:
             if not self.quiet:
                 self.report({'INFO'}, "Scan complete. No orphaned data or legacy properties found.")
        elif migrated_count > 0:
             self.report({'INFO'}, f"Recovery complete. Migrated {migrated_count} legacy text block(s).")
        else:
             if not self.quiet:
                 self.report({'INFO'}, f"Scan complete. Found {total} valid components.")
             
        return {'FINISHED'}


# Export all operator classes for wildcard imports
__all__ = [
    'TEXT_TEXTURE_OT_refresh_preview',
    'TEXT_TEXTURE_OT_view_preview_zoom',
    'TEXT_TEXTURE_OT_open_panel',
    'TEXT_TEXTURE_OT_refresh_fonts',
    'TEXT_TEXTURE_OT_refresh_presets',
    'TEXT_TEXTURE_OT_add_overlay',
    'TEXT_TEXTURE_OT_remove_overlay',
    'TEXT_TEXTURE_OT_set_anchor_point',
    'TEXT_TEXTURE_OT_sync_margins',
    'TEXT_TEXTURE_OT_duplicate_overlay',
    'TEXT_TEXTURE_OT_delete_overlay',
    'TEXT_TEXTURE_OT_move_overlay',
    'TEXT_TEXTURE_OT_recover_data',
]
