"""
Text Texture Generator - UI Panels Module
Contains all UI panel classes for different editor contexts.
"""

import bpy
from bpy.types import Panel
from ..core.generation_engine import generate_preview
from ..utils.constants import (
    is_free_version, get_version_badge_text, get_version_badge_icon,
    get_upgrade_hint_text, should_show_feature_lock,
    get_feature_availability_text, get_version_info_details,
    has_image_overlays, has_basic_utilities, has_presets,
    has_normal_maps, has_batch_processing, has_advanced_utilities,
    has_advanced_styling, has_text_fitting
)
from .font_helpers import font_size_ui_state


# ============================================================================
# SHARED UI COMPONENTS
# ============================================================================

def is_operator_available(operator_id):
    """Check if an operator is available/registered in Blender"""
    try:
        import bpy
        # Try to get operator class - if it doesn't exist, this will fail
        return hasattr(bpy.ops, operator_id.split('.')[0]) and hasattr(getattr(bpy.ops, operator_id.split('.')[0]), operator_id.split('.')[1])
    except:
        return False

def create_premium_lock_function(feature_name=None):
    """Create a standard premium lock function for a specific feature
    
    Args:
        feature_name: Optional feature name for context-specific hints
        
    Returns:
        A function that can be used as fallback_content_func in safe_operator_call
    """
    def show_premium_lock(fallback_layout):
        fallback_layout.enabled = False
        fallback_layout.label(text="🔒 Pro Feature", icon='LOCKED')
    return show_premium_lock

def safe_operator_call(layout, operator_id, fallback_content_func=None, **kwargs):
    """Safely call an operator, showing premium content if operator doesn't exist
    
    Args:
        layout: Blender UI layout object
        operator_id: String ID of operator (e.g., 'text_texture.add_overlay')
        fallback_content_func: Function to call if operator doesn't exist
        **kwargs: Arguments to pass to layout.operator()
    
    Returns:
        Operator reference if successful, None if operator doesn't exist
    """
    if is_operator_available(operator_id):
        return layout.operator(operator_id, **kwargs)
    else:
        # Operator doesn't exist - show premium lock content instead
        if fallback_content_func:
            fallback_content_func(layout)
        else:
            # Default fallback - show generic premium lock
            lock_row = layout.row()
            lock_row.enabled = False
            lock_row.label(text="🔒 Pro Feature", icon='LOCKED')
        return None

def draw_collapsible_header(layout, prop_name, text, icon='TRIA_DOWN'):
    pass
    """Draw a collapsible section header with expand/collapse arrow"""
    props = bpy.context.scene.text_texture_props
    expanded = getattr(props, prop_name)
    
    box = layout.box()
    header_row = box.row()
    
    # Draw arrow icon and toggle expanded state
    arrow_icon = 'TRIA_DOWN' if expanded else 'TRIA_RIGHT'
    header_row.prop(props, prop_name, text="", icon=arrow_icon, emboss=False)
    header_row.label(text=text, icon=icon)
    
    return box if expanded else None

def draw_premium_collapsible_section(layout, prop_name, title, icon, availability_func):
    """Draw a collapsible header that locks when feature is unavailable."""
    header_row = layout.row(align=True)
    try:
        available = availability_func()
    except Exception:
        available = False
    if not available:
        header_row.enabled = False
        lock_header = header_row.row()
        lock_header.label(text=title, icon=icon)
        lock_header.label(text="🔒 PRO", icon='LOCKED')
        return None
    return draw_collapsible_header(header_row, prop_name, title, icon)

def draw_version_badge(layout):
    pass
    """Draw version badge in panel header"""
    badge_row = layout.row(align=True)
    badge_row.scale_x = 0.7
    badge_row.scale_y = 0.8
    badge_row.alignment = 'RIGHT'
    
    # Simple label-based badge (more reliable than operator)
    badge_label = badge_row.label(text=get_version_badge_text())
    if is_free_version():
        pass
        badge_row.label(text="", icon='GIFT')
    else:
        pass
        badge_row.label(text="", icon='STAR')

def draw_feature_lock_indicator(layout, feature_name, show_hint=True):
    """Draw feature lock indicator for premium features"""
    if should_show_feature_lock(feature_name):
        # Create a box for better visual separation
        lock_box = layout.box()
        
        # Main lock indicator with proper vertical centering using row alignment
        lock_row = lock_box.row(align=True)
        lock_row.scale_y = 1.2  # Slightly larger for better visual balance
        lock_row.alignment = 'CENTER'
        
        # Use a single row with proper alignment instead of split for better centering
        # Add icon with proper spacing
        icon_col = lock_row.column(align=True)
        icon_col.scale_x = 0.8
        icon_col.alignment = 'CENTER'
        icon_col.label(text="", icon='LOCKED')
        
        # Add text with proper alignment
        text_col = lock_row.column(align=True)
        text_col.alignment = 'CENTER'
        text_col.label(text="🔒 Pro Feature")
        
        if show_hint:
            hint_row = lock_box.row()
            hint_row.scale_y = 0.8
            hint_row.alignment = 'CENTER'
            hint_row.label(text=get_upgrade_hint_text(feature_name))

def draw_version_info_section(layout, props):
    pass
    """Draw version information display section"""
    info_box = layout.box()
    info_box.label(text="Version Information", icon='INFO')
    
    # Version details
    version_info = get_version_info_details()
    
    col = info_box.column(align=True)
    col.scale_y = 0.8
    
    # Basic version info
    col.label(text=f"Version: {version_info['version_type']}")
    col.label(text=get_feature_availability_text())
    
    # Current limits
    limits_col = col.column(align=True)
    limits_col.separator()
    limits_col.label(text="Current Limits:")
    max_texture_display = version_info['max_texture_size']
    if isinstance(max_texture_display, (int, float)):
        max_texture_display = f"{int(max_texture_display)}px"
    limits_col.label(text=f"• Max texture size: {max_texture_display}")
    limits_col.label(text=f"• Active features: {version_info['features_enabled']}")
    
    # Feature availability status
    col.separator()
    availability_col = col.column(align=True)
    availability_col.label(text="Feature Status:")
    
    if has_presets():
        pass
        availability_col.label(text="• Presets: ✓ Available", icon='CHECKMARK')
    else:
        pass
        availability_col.label(text="• Presets: 🔒 Pro Only", icon='LOCKED')
    
    if has_image_overlays():
        pass
        availability_col.label(text="• Image Overlays: ✓ Available", icon='CHECKMARK')
    else:
        pass
        availability_col.label(text="• Image Overlays: 🔒 Pro Only", icon='LOCKED')
    
    if has_basic_utilities():
        pass
        availability_col.label(text="• Basic Tools: ✓ Available", icon='CHECKMARK')
    else:
        pass
        availability_col.label(text="• Basic Tools: 🔒 Pro Only", icon='LOCKED')
    
    if has_advanced_utilities():
        pass
        availability_col.label(text="• Advanced Tools: ✓ Available", icon='CHECKMARK')
    else:
        pass
        availability_col.label(text="• Advanced Tools: 🔒 Pro Only", icon='LOCKED')
    
    # Upgrade hint for free version
    if version_info['upgrade_available']:
        pass
        col.separator()
        upgrade_box = info_box.box()
        upgrade_box.scale_y = 0.9
        upgrade_row = upgrade_box.row()
        upgrade_row.alignment = 'CENTER'
        upgrade_row.label(text="💡 Upgrade to Pro for all features", icon='STAR')

def draw_text_input_section(layout, props):
    pass
    """Draw the main text input field with dimensions."""
    content = layout.column(align=True)
    content.use_property_split = False
    content.use_property_decorate = False
    
    row = content.row(align=True)
    text_col = row.column(align=True)
    text_col.prop(props, "text", text="")
    
    dimensions_col = row.column(align=True)
    dimensions_col.use_property_split = False
    dimensions_col.use_property_decorate = False
    dim_row = dimensions_col.row(align=True)
    dim_row.prop(props, "texture_width", text="")
    dim_row.prop(props, "texture_height", text="")
    
def draw_font_dropdown_section(layout, props):
    pass
    """Draw basic font dropdown for top level"""
    row = layout.row(align=True)
    row.prop(props, "font_path", text="")
    row.operator("text_texture.refresh_fonts", text="", icon='FILE_REFRESH')

def draw_generate_button(layout):
    pass
    """Draw the main generate button"""
    row = layout.row()
    row.scale_y = 1.5
    row.operator("text_texture.generate", text="Generate Text Texture", icon='IMAGE_DATA')

def draw_reset_button(layout):
    pass
    """Draw button to reset settings to defaults"""
    row = layout.row()
    row.alignment = 'RIGHT'
    row.scale_y = 1.0
    row.operator("text_texture.reset_settings", text="Reset Settings", icon='FILE_REFRESH')

def _iter_components_by_placement(props, placement_mode):
    """Yield (index, component) pairs filtered by placement mode."""
    try:
        overlays = list(props.image_overlays)
    except TypeError:
        overlays = props.image_overlays
    
    scene_name = getattr(bpy.context.scene, "name", "UNKNOWN")
    print(f"DEBUG: _iter_components_by_placement [Scene: {scene_name}] - TOTAL overlays in collection: {len(overlays)} (Checking for mode: {placement_mode})")
    
    # Detailed dumping of EVERY component regardless of filter
    for i, comp in enumerate(overlays):
        name = getattr(comp, "name", "unnamed")
        pmode = getattr(comp, "placement_mode", "NONE")
        ctype = getattr(comp, "component_type", "NONE")
        enabled = getattr(comp, "enabled", False)
        print(f"  -> Collection Item {i}: Name='{name}', Mode='{pmode}', Type='{ctype}', Enabled={enabled}")
    
    for index, component in enumerate(overlays):
        comp_name = getattr(component, "name", f"Overlay {index}")
        comp_placement = getattr(component, "placement_mode", 'ABSOLUTE')
        
        if not comp_placement or comp_placement not in ('ABSOLUTE', 'PREPEND', 'APPEND'):
            print(f"DEBUG: Component '{comp_name}' has invalid placement '{comp_placement}'. Forcing to ABSOLUTE.")
            comp_placement = 'ABSOLUTE'
            
        if comp_placement == placement_mode:
            print(f"DEBUG: MATCH FOUND for '{comp_name}' (Index: {index}, Type: {getattr(component, 'component_type', 'UNKNOWN')})")
            yield index, component
        else:
            # Only log skips if there were actually components to skip
            print(f"DEBUG: Skipping '{comp_name}' (Placement '{comp_placement}' != requested '{placement_mode}')")


def _draw_component_header(row, component):
    """Draw shared header controls for a component."""
    row.prop(component, "enabled", text="", icon='CHECKBOX_HLT' if component.enabled else 'CHECKBOX_DEHLT')
    name_row = row.row(align=True)
    name_row.prop(component, "name", text="")
    name_row.prop(component, "component_type", text="")


def _draw_component_footer(row, props, index):
    """Draw the footer action buttons for a component."""
    premium_lock = create_premium_lock_function()
    
    dup_op = safe_operator_call(row, "text_texture.duplicate_overlay", premium_lock, text="", icon='DUPLICATE')
    if dup_op:
        dup_op.overlay_index = index
    
    del_op = safe_operator_call(row, "text_texture.delete_overlay", premium_lock, text="", icon='TRASH')
    if del_op:
        del_op.overlay_index = index
    
    move_up = safe_operator_call(row, "text_texture.move_overlay", premium_lock, text="", icon='TRIA_UP')
    if move_up:
        move_up.overlay_index = index
        move_up.direction = 'UP'
    
    move_down = safe_operator_call(row, "text_texture.move_overlay", premium_lock, text="", icon='TRIA_DOWN')
    if move_down:
        move_down.overlay_index = index
        move_down.direction = 'DOWN'


def _draw_component_details(container, component):
    """Render component-specific detail controls."""
    details_col = container.column(align=True)
    details_col.enabled = component.enabled
    
    details_col.prop(component, "placement_mode", text="Placement")
    
    if component.component_type == 'TEXT':
        details_col.prop(component, "text_content", text="Text")
        details_col.prop(component, "text_spacing", text="Spacing (%)")
    else:
        details_col.prop(component, "image_path", text="Image File")
        details_col.prop(component, "text_spacing", text="Spacing (%)")
        details_col.prop(component, "image_spacing", text="Component Spacing (%)")
    
    if component.placement_mode == 'ABSOLUTE':
        pos_row = details_col.row(align=True)
        pos_row.prop(component, "x_position", text="X")
        pos_row.prop(component, "y_position", text="Y")
    
    transform_row = details_col.row(align=True)
    transform_row.prop(component, "scale", text="Scale")
    transform_row.prop(component, "rotation", text="Rotation")
    transform_row.prop(component, "z_index", text="Z-Level")


def draw_component_section(layout, props, placement_mode, title, icon):
    """Render a section for a specific placement mode."""
    section = layout.box()
    section.use_property_split = False
    section.use_property_decorate = False
    
    header = section.row(align=True)
    header.label(text=title, icon=icon)
    
    # Add new component button
    add_row = section.row(align=True)
    premium_lock = create_premium_lock_function()
    add_op = safe_operator_call(
        add_row,
        "text_texture.add_overlay",
        premium_lock,
        text="Add Component",
        icon='ADD'
    )
    if add_op:
        add_op.placement_mode = placement_mode
    
    components = list(_iter_components_by_placement(props, placement_mode))
    print(f"DEBUG: draw_component_section for {placement_mode} - found {len(components)} components")
    if not components:
        section.label(text="No components added", icon='INFO')
        return
    
    for index, component in components:
        box = section.box()
        header_row = box.row(align=True)
        _draw_component_header(header_row, component)
        _draw_component_footer(header_row, props, index)
        _draw_component_details(box, component)

def draw_composition_section(layout, props):
    """Draw combined composition controls for text and image components."""
    # Bulletproof Visibility: Even if locked, show header with count if data exists
    has_overlays = has_image_overlays()
    total_count = len(props.image_overlays)
    if not has_overlays:
        if total_count > 0:
             layout.label(text=f"Composition ({total_count}) 🔒 PRO", icon='LOCKED')
             layout.label(text="Upgrade to edit existing components")
        else:
             draw_feature_lock_indicator(layout, 'image_overlays')
        return
    
    content = layout.column(align=True)
    content.use_property_split = False
    content.use_property_decorate = False
    
    # Enhanced Header with Counter
    count_abs = len(list(_iter_components_by_placement(props, 'ABSOLUTE')))
    count_pre = len(list(_iter_components_by_placement(props, 'PREPEND')))
    count_app = len(list(_iter_components_by_placement(props, 'APPEND')))
    
    draw_component_section(content, props, 'ABSOLUTE', f"Absolute Components ({count_abs})", 'CURSOR')
    draw_component_section(content, props, 'PREPEND', f"Prepended Components ({count_pre})", 'TRIA_LEFT_BAR')
    draw_component_section(content, props, 'APPEND', f"Appended Components ({count_app})", 'TRIA_RIGHT_BAR')
    
    # Recovery Utility (Safety Net)
    content.separator(factor=1.5)
    diag_box = content.box()
    diag_row = diag_box.row(align=True)
    diag_row.label(text="Data Status:", icon='INFO')
    if total_count > 0:
        diag_row.label(text="✓ OK", icon='CHECKMARK')
    else:
        diag_row.label(text="⚠ EMPTY", icon='ERROR')
    
    diag_box.operator("text_texture.recover_data", text="Scan for Lost Components", icon='FILE_REFRESH')

def draw_positioning_section(layout, props):
    pass
    """Draw positioning and alignment controls with streamlined spacing."""
    from ..utils.system import get_anchor_point_matrix
    
    content = layout.column(align=True)
    content.use_property_split = True
    content.use_property_decorate = False
    
    content.label(text="Placement Mode", icon='ANCHOR_CENTER')
    content.prop(props, "position_mode", text="")
    content.separator(factor=0.6)
    
    if props.position_mode == 'PRESET':
        pass
        # Anchor selection grid
        anchor_box = content.box()
        anchor_box.use_property_split = False
        anchor_box.use_property_decorate = False
        anchor_box.label(text="Anchor Point", icon='ANCHOR_TOP')
        
        anchor_matrix = get_anchor_point_matrix()
        for row in anchor_matrix:
            pass
            grid_row = anchor_box.row(align=True)
            grid_row.scale_y = 1.15
            for anchor in row:
                pass
                premium_lock = create_premium_lock_function()
                is_active = anchor == props.anchor_point
                op = safe_operator_call(
                    grid_row,
                    "text_texture.set_anchor_point",
                    premium_lock,
                    text="●" if is_active else "○",
                    depress=is_active
                )
                if op:
                    op.anchor_point = anchor
        
        anchor_box.separator(factor=0.6)
        
        # Margin controls
        margin_box = content.box()
        margin_box.use_property_split = True
        margin_box.use_property_decorate = False
        header_row = margin_box.row(align=True)
        header_row.label(text="Margins", icon='ARROW_LEFTRIGHT')
        header_row.prop(
            props,
            "margins_linked",
            text="",
            icon='LINKED' if props.margins_linked else 'UNLINKED',
            toggle=True
        )
        
        margins_row = margin_box.row(align=True)
        margins_row.prop(props, "margin_x", text="X")
        y_col = margins_row.row(align=True)
        y_col.enabled = not props.margins_linked
        y_col.prop(props, "margin_y", text="Y")
        
        margin_box.separator(factor=0.6)
        
        # Pixel offsets
        offset_box = content.box()
        offset_box.use_property_split = True
        offset_box.use_property_decorate = False
        offset_box.label(text="Fine-tune (pixels)", icon='DRIVER_DISTANCE')
        offset_row = offset_box.row(align=True)
        offset_row.prop(props, "offset_x", text="X")
        offset_row.prop(props, "offset_y", text="Y")
        
    else:
        pass
        manual_box = content.box()
        manual_box.use_property_split = True
        manual_box.use_property_decorate = False
        manual_box.label(text="Manual Placement", icon='DRIVER_TRANSFORM')
        manual_box.prop(props, "manual_position_unit", text="Unit")
        manual_row = manual_box.row(align=True)
        manual_row.prop(props, "manual_position_x", text="X")
        manual_row.prop(props, "manual_position_y", text="Y")
    
    content.separator(factor=0.6)
    content.prop(props, "constrain_to_canvas")

def draw_font_settings_section(layout, props):
    pass
    """Draw unified font sizing and fitting controls."""
    content = layout.column(align=True)
    content.use_property_split = True
    content.use_property_decorate = False

    sizing_box = content.box()
    sizing_box.use_property_split = True
    sizing_box.use_property_decorate = False
    sizing_box.label(text="Size & Text Fitting", icon='FULLSCREEN_ENTER')

    manual_enabled, status_message = font_size_ui_state(props)
    manual_row = sizing_box.row(align=True)
    manual_row.enabled = manual_enabled
    manual_row.prop(props, "font_size", text="Manual Size")

    if status_message:
        info_row = sizing_box.row()
        info_row.label(text=status_message, icon='INFO')

    if has_text_fitting():
        toggle_row = sizing_box.row(align=True)
        toggle_row.prop(props, "enable_text_fitting", text="Enable Text Fitting", toggle=True)

        if props.enable_text_fitting:
            sizing_box.separator(factor=0.5)

            mode_row = sizing_box.row(align=True)
            mode_row.prop(props, "text_fitting_mode", text="Mode")

            margin_row = sizing_box.row(align=True)
            margin_row.prop(props, "text_fitting_margin", text="Margin", slider=True)

            limit_row = sizing_box.row(align=True)
            limit_row.prop(props, "min_font_size", text="Min Size")
            limit_row.prop(props, "max_font_size", text="Max Size")
    else:
        sizing_box.separator(factor=0.5)
        draw_feature_lock_indicator(sizing_box, 'text_fitting', show_hint=False)

    content.separator(factor=0.8)

    selection_box = content.box()
    selection_box.use_property_split = True
    selection_box.use_property_decorate = False
    selection_box.label(text="Font Selection", icon='FONT_DATA')

    font_row = selection_box.row(align=True)
    font_row.prop(props, "font_path", text="")
    font_row.operator("text_texture.refresh_fonts", text="", icon='FILE_REFRESH')

    selection_box.prop(props, "use_custom_font")
    if props.use_custom_font:
        pass
        selection_box.prop(props, "custom_font_path", text="")

    selection_box.separator(factor=0.5)
    selection_box.prop(props, "text_align", text="Alignment")

def draw_colors_section(layout, props):
    pass
    """Draw color controls for text and background"""
    layout.label(text="Text Color:", icon='COLOR')
    layout.prop(props, "text_color", text="")
    
    layout.separator()
    layout.label(text="Background Color:", icon='IMAGE_PLANE')
    layout.prop(props, "background_transparent")
    if not props.background_transparent:
        pass
        layout.prop(props, "background_color", text="")

def draw_preview_options_section(layout, props):
    pass
    """Draw preview options (preview-specific settings only)"""
    layout.prop(props, "preview_size", text="Preview Size")
    layout.separator()
    layout.label(text="Preview Background Display:", icon='SCENE')
    layout.prop(props, "preview_bg_type", text="Background")
    if props.preview_bg_type == 'color':
        pass
        layout.prop(props, "preview_bg_color", text="Preview Display Color")
    elif props.preview_bg_type == 'gradient':
        layout.prop(props, "preview_bg_color", text="Color 1")
        layout.prop(props, "preview_bg_color2", text="Color 2")

def draw_presets_section(layout, props):
    pass
    """Draw unified presets save/load controls"""
    # Check if presets are available, show lock if not
    if not has_presets():
        pass
        draw_feature_lock_indicator(layout, 'presets')
        return
    
    col = layout.column(align=True)
    
    # Save preset controls
    save_row = col.row(align=True)
    save_row.prop(props, "new_preset_name", text="", placeholder="Preset Name")
    
    premium_lock = create_premium_lock_function()
    safe_operator_call(save_row, "text_texture.save_preset", premium_lock,
                       text="Save", icon='FILE_NEW')
    
    save_location_row = col.row(align=True)
    save_location_row.prop(props, "save_with_blend_file", text="Project-specific (saved inside this .blend)")
    
    col.separator()
    
    # Import/export/refresh controls
    backup_row = col.row(align=True)
    export_lock = create_premium_lock_function()
    import_lock = create_premium_lock_function()
    safe_operator_call(backup_row, "text_texture.export_presets", export_lock,
                       text="Export Backup", icon='EXPORT')
    safe_operator_call(backup_row, "text_texture.import_presets", import_lock,
                       text="Import Backup", icon='IMPORT')
    
    utility_row = col.row(align=True)
    refresh_lock = create_premium_lock_function()
    safe_operator_call(utility_row, "text_texture.refresh_presets", refresh_lock,
                       text="Refresh List", icon='FILE_REFRESH')
    
    col.separator()
    
    total_presets = len(props.presets)
    
    if total_presets:
        pass
        blend_count = len([preset for preset in props.presets if preset.source == 'BLEND_FILE'])
        persistent_count = total_presets - blend_count
        
        summary_row = col.row(align=True)
        summary_row.label(text=f"{total_presets} presets", icon='PRESET')
        summary_row.label(text=f"{blend_count} project", icon='FILE_BLEND')
        summary_row.label(text=f"{persistent_count} global", icon='FILE_CACHE')
        
        search_row = col.row(align=True)
        search_row.prop(props, "preset_search_query", text="", icon='VIEWZOOM')
        if getattr(props, "preset_search_query", "").strip():
            search_row.operator("text_texture.clear_preset_search", text="", icon='PANEL_CLOSE')
        
        # Prepare sorted and filtered presets for display
        search_query = getattr(props, "preset_search_query", "").strip().lower()
        sorted_presets = sorted(props.presets, key=lambda p: p.name.lower())
        if search_query:
            visible_presets = [preset for preset in sorted_presets if search_query in preset.name.lower()]
        else:
            visible_presets = sorted_presets
        
        if visible_presets:
            pass
            for preset in visible_presets:
                pass
                row = col.row(align=True)
                row.scale_y = 0.95
                
                is_active = getattr(props, "last_loaded_preset", "") == preset.name
                load_icon = 'CHECKMARK' if is_active else 'PRESET'
                
                load_lock = create_premium_lock_function()
                load_btn = safe_operator_call(row, "text_texture.load_preset", load_lock,
                                              text=preset.name, icon=load_icon)
                if load_btn:
                    load_btn.preset_name = preset.name
                
                source_icon = 'FILE_BLEND' if preset.source == 'BLEND_FILE' else 'FILE_CACHE'
                source_label = "Project" if preset.source == 'BLEND_FILE' else "Global"
                row.label(text=source_label, icon=source_icon)
                
                actions = row.row(align=True)
                actions.alignment = 'RIGHT'
                
                overwrite_lock = create_premium_lock_function()
                overwrite_btn = safe_operator_call(actions, "text_texture.save_preset", overwrite_lock,
                                                   text="", icon='FILE_REFRESH')
                if overwrite_btn:
                    overwrite_btn.overwrite = True
                    overwrite_btn.preset_name = preset.name
                
                delete_lock = create_premium_lock_function()
                delete_btn = safe_operator_call(actions, "text_texture.delete_preset", delete_lock,
                                                text="", icon='TRASH')
                if delete_btn:
                    delete_btn.preset_name = preset.name
        else:
            pass
            col.label(text="No presets match your search", icon='INFO')
    else:
        pass
        col.label(text="No presets yet", icon='INFO')
        col.label(text="Save your current settings to start your preset library.")

def draw_shader_section(layout, props):
    pass
    """Draw shader generation controls"""
    # Check if shader generation is available
    from ..utils.constants import has_shader_generation
    if not has_shader_generation():
        draw_feature_lock_indicator(layout, 'shader_generation')
        return
    
    # Create Shader Button (as requested)
    row = layout.row()
    row.scale_y = 1.5
    row.operator("text_texture.generate_shader", text="Create Shader", icon='MATERIAL')
    
    plane_row = layout.row()
    plane_row.scale_y = 1.3
    plane_row.operator("text_texture.generate_plane", text="Create Plane", icon='MESH_GRID')
    
    layout.separator()
    
    # Clean minimalist controls
    col = layout.column(align=True)
    col.prop(props, "shader_type", text="Type")
    
    # Show relevant options based on shader type
    if props.shader_type == 'PRINCIPLED':
        pass
        col.prop(props, "shader_connection", text="Connect")
        if props.shader_connection == 'EMISSION':
            pass
            col.prop(props, "emission_strength", text="Strength")
    elif props.shader_type == 'EMISSION':
        col.prop(props, "emission_strength", text="Strength")
    
    layout.separator()
    
    # Simple toggles
    col = layout.column(align=True)
    col.prop(props, "use_alpha", text="Use Alpha Channel")
    col.prop(props, "auto_assign_material", text="Auto-Assign to Object")
    
    # Clean status info
    if props.auto_assign_material:
        pass
        layout.separator()
        info_row = layout.row()
        info_row.scale_y = 0.8
        try:
            pass
            context = bpy.context
            if context and context.active_object and context.active_object.type in ['MESH', 'CURVE']:
                pass
                info_row.label(text=f"→ {context.active_object.name}", icon='CHECKMARK')
            else:
                pass
                info_row.label(text="Select mesh/curve object", icon='INFO')
        except:
            pass
            info_row.label(text="Select mesh/curve object", icon='INFO')

def draw_shader_options_only(layout, props):
    pass
    """Draw only shader options without the Create button - for collapsible section"""
    # Check if shader generation is available
    from ..utils.constants import has_shader_generation
    if not has_shader_generation():
        draw_feature_lock_indicator(layout, 'shader_generation')
        return
    
    # Clean grid layout for shader options
    grid = layout.grid_flow(row_major=True, columns=2, align=True)
    
    grid.prop(props, "shader_type", text="Type")
    
    if props.shader_type == 'PRINCIPLED':
        pass
        grid.prop(props, "shader_connection", text="Connect")
        if props.shader_connection == 'EMISSION':
            pass
            grid.prop(props, "emission_strength", text="Strength")
    elif props.shader_type == 'EMISSION':
        grid.prop(props, "emission_strength", text="Strength")
    
    # Simple row for toggles
    layout.separator()
    row = layout.row(align=True)
    row.prop(props, "use_alpha", toggle=True)
    row.prop(props, "auto_assign_material", toggle=True)
    
    # Shadow, reflection, and backfacing toggles
    row = layout.row(align=True)
    row.prop(props, "disable_shadows", toggle=True)
    row.prop(props, "disable_reflections", toggle=True)
    row.prop(props, "disable_backfacing", toggle=True)

def draw_normal_maps_section(layout, props):
    pass
    """Draw normal map generation controls"""
    # Main toggle for normal map generation
    layout.prop(props, "generate_normal_map", text="Generate Normal Map", icon='TEXTURE')
    
    # Show controls only if normal map generation is enabled
    if props.generate_normal_map:
        pass
        layout.separator()
        
        # Normal map settings in a clean layout
        col = layout.column(align=True)
        col.prop(props, "normal_map_strength", text="Strength", slider=True)
        col.prop(props, "normal_map_blur_radius", text="Blur Radius", slider=True)
        
        layout.separator()
        layout.prop(props, "normal_map_invert", text="Invert (Emboss ↔ Deboss)")
        
        # Info box with usage tips
        layout.separator()
        info_box = layout.box()
        info_box.scale_y = 0.8
        info_box.label(text="💡 Normal maps add depth and detail", icon='INFO')
        info_box.label(text="• Higher strength = more pronounced effect")
        info_box.label(text="• Blur smooths sharp edges")
        info_box.label(text="• Invert changes raised/recessed effect")

def draw_stroke_section(layout, props):
    pass
    """Draw stroke and outline controls"""
    # Check if stroke effects are available
    from ..utils.constants import has_stroke_effects
    if not has_stroke_effects():
        draw_feature_lock_indicator(layout, 'stroke_effects')
        return
    
    # Main toggle for stroke
    layout.prop(props, "enable_stroke", text="Enable Stroke", icon='MOD_OUTLINE')
    
    # Show controls only if stroke is enabled
    if props.enable_stroke:
        pass
        layout.separator()
        
        # Stroke width and color
        col = layout.column(align=True)
        col.prop(props, "stroke_width", text="Width", slider=True)
        col.prop(props, "stroke_color", text="Color")
        
        layout.separator()
        
        # Stroke position
        layout.prop(props, "stroke_position", text="Position")
        
        # Info box with usage tips
        layout.separator()
        info_box = layout.box()
        info_box.scale_y = 0.8
        info_box.label(text="💡 Stroke adds outline to text:", icon='INFO')
        
        if props.stroke_position == 'OUTER':
            pass
            info_box.label(text="• Outer: Expands text bounds outward")
        elif props.stroke_position == 'INNER':
            info_box.label(text="• Inner: Shrinks text, stroke inside")
        elif props.stroke_position == 'CENTER':
            info_box.label(text="• Center: Stroke on text edge")
        
        info_box.label(text="• Width 0 = no stroke")

def draw_shadow_glow_section(layout, props):
    pass
    """Draw shadow and glow effects controls"""
    # Check if shadow/glow effects are available
    from ..utils.constants import has_shadow_glow_effects
    if not has_shadow_glow_effects():
        draw_feature_lock_indicator(layout, 'shadow_glow_effects')
        return
    
    # Drop shadow section
    layout.prop(props, "enable_shadow", text="Enable Drop Shadow", icon='SHADERFX')
    
    if props.enable_shadow:
        pass
        layout.separator()
        
        # Shadow offset controls in a row
        offset_row = layout.row(align=True)
        offset_row.prop(props, "shadow_offset_x", text="X Offset")
        offset_row.prop(props, "shadow_offset_y", text="Y Offset")
        
        # Shadow properties
        col = layout.column(align=True)
        col.prop(props, "shadow_blur", text="Shadow Blur", slider=True)
        col.prop(props, "shadow_spread", text="Shadow Spread", slider=True)
        col.prop(props, "shadow_color", text="Shadow Color")
    
    layout.separator()
    
    # Glow section
    layout.prop(props, "enable_glow", text="Enable Glow", icon='LIGHT_SUN')
    
    if props.enable_glow:
        pass
        layout.separator()
        
        # Glow properties
        col = layout.column(align=True)
        col.prop(props, "glow_blur", text="Glow Blur", slider=True)
        col.prop(props, "glow_color", text="Glow Color")
    
    # Info box with usage tips
    if props.enable_shadow or props.enable_glow:
        pass
        layout.separator()
        info_box = layout.box()
        info_box.scale_y = 0.8
        info_box.label(text="💡 Shadow & Glow effects:", icon='INFO')
        
        if props.enable_shadow:
            pass
            info_box.label(text="• Drop shadow: offset + blur for depth")
        if props.enable_glow:
            pass
            info_box.label(text="• Glow: blur without offset for aura effect")
        
        info_box.label(text="• Higher blur = softer effect")
        info_box.label(text="• Alpha controls effect intensity")

def draw_blur_section(layout, props):
    pass
    """Draw blur effects controls"""
    # Check if blur effects are available
    from ..utils.constants import has_blur_effects
    if not has_blur_effects():
        draw_feature_lock_indicator(layout, 'blur_effects')
        return
    
    # Main toggle for blur
    layout.prop(props, "enable_blur", text="Enable Blur", icon='MOD_SMOOTH')
    
    # Show controls only if blur is enabled
    if props.enable_blur:
        pass
        layout.separator()
        
        # Blur radius setting
        layout.prop(props, "blur_radius", text="Blur Radius", slider=True)
        
        # Info box with usage tips
        layout.separator()
        info_box = layout.box()
        info_box.scale_y = 0.8
        info_box.label(text="💡 Blur effect softens text edges:", icon='INFO')
        info_box.label(text="• Applied to main text content only")
        info_box.label(text="• Higher radius = softer/more blurred")
        info_box.label(text="• Works with all other effects")
        info_box.label(text="• Radius 0 = no blur effect")


# ============================================================================
# UI PANELS
# ============================================================================

class TEXT_TEXTURE_PT_panel(Panel):
    pass
    """Main Panel in Shader Editor"""
    bl_label = "Text Texture Generator"
    bl_idname = "TEXT_TEXTURE_PT_panel"
    bl_space_type = 'NODE_EDITOR'
    bl_region_type = 'UI'
    bl_category = "Tool"
    
    @classmethod
    def poll(cls, context):
        """Show panel in Shader Editor only"""
        if context.space_data.type == 'NODE_EDITOR':
            if hasattr(context.space_data, 'tree_type'):
                return context.space_data.tree_type == 'ShaderNodeTree'
            else:
                # Allow panel even without tree_type (sometimes happens)
                return True
        
        return False
    
    def draw(self, context):
        pass
        layout = self.layout
        props = context.scene.text_texture_props
        
        # TOP LEVEL - Always Visible Controls
        
        # Text Input
        box = layout.box()
        box.label(text="Text:", icon='TEXT')
        draw_text_input_section(box, props)
        
        
        # Generate Button
        layout.separator(factor=0.5)
        draw_generate_button(layout)
        
        # CREATE SHADER BUTTON - WITH PROPER RESTRICTION
        layout.separator(factor=0.5)
        create_shader_row = layout.row()
        create_shader_row.scale_y = 1.5
        
        # Check if shader generation is available
        from ..utils.constants import has_shader_generation
        if has_shader_generation():
            create_shader_row.operator("text_texture.generate_shader", text="Create Shader", icon='MATERIAL')
        else:
            # Show locked shader button for free version
            lock_row = create_shader_row.row()
            lock_row.enabled = False
            lock_row.operator("text_texture.generate_shader", text="🔒 Create Shader (Pro Only)", icon='LOCKED')

        plane_row = layout.row()
        plane_row.scale_y = 1.3
        if has_shader_generation():
            plane_row.operator("text_texture.generate_plane", text="Create Plane", icon='MESH_GRID')
        else:
            plane_lock_row = plane_row.row()
            plane_lock_row.enabled = False
            plane_lock_row.label(text="🔒 Create Plane (Pro Only)", icon='LOCKED')
        
        # Preview Button - ALWAYS available (core functionality for all users)
        layout.separator(factor=0.5)
        preview_row = layout.row()
        preview_row.scale_y = 1.5
        preview_row.operator("text_texture.preview", text="Preview Texture", icon='HIDE_OFF')
        
        layout.separator(factor=0.6)
        draw_reset_button(layout)
        
        layout.separator(factor=1.0)
        
        # COLLAPSIBLE SECTIONS - FREE FEATURES FIRST
        
        # === FREE FEATURES ===
        
        # Font Settings Section (collapsed by default)
        font_section = draw_collapsible_header(layout, "expand_font_settings", "Font Settings", 'FONT_DATA')
        if font_section:
            pass
            draw_font_settings_section(font_section, props)
        
        # Positioning & Layout Section (collapsed by default) - FREE FEATURE moved to free group
        position_section = draw_collapsible_header(layout, "expand_positioning", "Positioning & Layout", 'ANCHOR_CENTER')
        if position_section:
            draw_positioning_section(position_section, props)
        
        # Colors Section (collapsed by default)
        colors_section = draw_collapsible_header(layout, "expand_colors", "Colors", 'COLOR')
        if colors_section:
            pass
            draw_colors_section(colors_section, props)
        
        # === PREMIUM FEATURES ===
        
        # Shader Section (collapsed by default) - ONLY OPTIONS, NOT THE BUTTON
        shader_header_row = layout.row(align=True)
        
        # Gray out header if locked and prevent expansion
        from ..utils.constants import has_shader_generation
        if not has_shader_generation():
            shader_header_row.enabled = False
            # Don't allow expansion for locked features
            shader_expanded = None
            # Show lock indicator instead of expandable header
            lock_header = shader_header_row.row()
            lock_header.label(text="Shader Options", icon='SETTINGS')
            lock_header.label(text="🔒 PRO", icon='LOCKED')
        else:
            shader_expanded = draw_collapsible_header(shader_header_row, "expand_shader", "Shader Options", 'SETTINGS')
        
        # Only show content if available and expanded
        if shader_expanded:
            draw_shader_options_only(shader_expanded, props)
        
        # Composition Section (collapsed by default)
        composition_section = draw_premium_collapsible_section(
            layout,
            "expand_composition",
            "Composition",
            'SEQ_PREVIEW',
            has_image_overlays
        )
        if composition_section:
            draw_composition_section(composition_section, props)
        
        
        # Stroke Section (collapsed by default) - Show with premium indicator
        stroke_header_row = layout.row(align=True)
        
        # Gray out header if locked and prevent expansion
        from ..utils.constants import has_stroke_effects
        if not has_stroke_effects():
            stroke_header_row.enabled = False
            # Don't allow expansion for locked features
            stroke_expanded = None
            # Show lock indicator instead of expandable header
            lock_header = stroke_header_row.row()
            lock_header.label(text="Stroke & Outlines", icon='MOD_OUTLINE')
            lock_header.label(text="🔒 PRO", icon='LOCKED')
        else:
            stroke_expanded = draw_collapsible_header(stroke_header_row, "expand_stroke", "Stroke & Outlines", 'MOD_OUTLINE')
        
        # Only show content if available and expanded
        if stroke_expanded:
            draw_stroke_section(stroke_expanded, props)
        
        # Shadow & Glow Section (collapsed by default) - Show with premium indicator
        shadow_glow_header_row = layout.row(align=True)
        
        # Gray out header if locked and prevent expansion
        from ..utils.constants import has_shadow_glow_effects
        if not has_shadow_glow_effects():
            shadow_glow_header_row.enabled = False
            # Don't allow expansion for locked features
            shadow_glow_expanded = None
            # Show lock indicator instead of expandable header
            lock_header = shadow_glow_header_row.row()
            lock_header.label(text="Shadow & Glow Effects", icon='SHADERFX')
            lock_header.label(text="🔒 PRO", icon='LOCKED')
        else:
            shadow_glow_expanded = draw_collapsible_header(shadow_glow_header_row, "expand_shadow_glow", "Shadow & Glow Effects", 'SHADERFX')
        
        # Only show content if available and expanded
        if shadow_glow_expanded:
            draw_shadow_glow_section(shadow_glow_expanded, props)
        
        # Blur Section (collapsed by default) - Show with premium indicator
        blur_header_row = layout.row(align=True)
        
        # Gray out header if locked and prevent expansion
        from ..utils.constants import has_blur_effects
        if not has_blur_effects():
            blur_header_row.enabled = False
            # Don't allow expansion for locked features
            blur_expanded = None
            # Show lock indicator instead of expandable header
            lock_header = blur_header_row.row()
            lock_header.label(text="Blur Effects", icon='MOD_SMOOTH')
            lock_header.label(text="🔒 PRO", icon='LOCKED')
        else:
            blur_expanded = draw_collapsible_header(blur_header_row, "expand_blur", "Blur Effects", 'MOD_SMOOTH')
        
        # Only show content if available and expanded
        if blur_expanded:
            draw_blur_section(blur_expanded, props)
        
        # Normal Maps Section (collapsed by default) - Show with premium indicator
        normal_header_row = layout.row(align=True)
        
        # Gray out header if locked and prevent expansion
        if not has_normal_maps():
            normal_header_row.enabled = False
            # Don't allow expansion for locked features
            normal_expanded = None
            # Show lock indicator instead of expandable header
            lock_header = normal_header_row.row()
            lock_header.label(text="Normal Maps", icon='TEXTURE')
            lock_header.label(text="🔒 PRO", icon='LOCKED')
        else:
            normal_expanded = draw_collapsible_header(normal_header_row, "expand_normal_maps", "Normal Maps", 'TEXTURE')
        
        # Only show content if available and expanded
        if normal_expanded:
            draw_normal_maps_section(normal_expanded, props)
        
        # Presets Section (collapsed by default) - Show with premium indicator
        presets_header_row = layout.row(align=True)
        
        # Gray out header if locked and prevent expansion
        if not has_presets():
            presets_header_row.enabled = False
            # Don't allow expansion for locked features
            presets_expanded = None
            # Show lock indicator instead of expandable header
            lock_header = presets_header_row.row()
            lock_header.label(text="Presets", icon='PRESET')
            lock_header.label(text="🔒 PRO", icon='LOCKED')
        else:
            presets_expanded = draw_collapsible_header(presets_header_row, "expand_presets", "Presets", 'PRESET')
        
        # Only show content if available and expanded
        if presets_expanded:
            draw_presets_section(presets_expanded, props)

class TEXT_TEXTURE_PT_panel_3d(Panel):
    pass
    """3D View Panel - Access from sidebar (N key)"""
    bl_label = "Text Texture Generator"
    bl_idname = "TEXT_TEXTURE_PT_panel_3d"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_category = "Tool"
    bl_options = {'DEFAULT_CLOSED'}
    
    def draw(self, context):
        pass
        layout = self.layout
        props = context.scene.text_texture_props
        
        # TOP LEVEL - Always Visible Controls
        
        # Text Input
        box = layout.box()
        box.label(text="Text:", icon='TEXT')
        draw_text_input_section(box, props)
        
        
        # Generate Button
        layout.separator(factor=0.5)
        draw_generate_button(layout)
        
        # CREATE SHADER BUTTON - WITH PROPER RESTRICTION
        layout.separator(factor=0.5)
        create_shader_row = layout.row()
        create_shader_row.scale_y = 1.5
        
        # Check if shader generation is available
        from ..utils.constants import has_shader_generation
        if has_shader_generation():
            create_shader_row.operator("text_texture.generate_shader", text="Create Shader", icon='MATERIAL')
        else:
            # Show locked shader button for free version
            lock_row = create_shader_row.row()
            lock_row.enabled = False
            lock_row.operator("text_texture.generate_shader", text="🔒 Create Shader (Pro Only)", icon='LOCKED')

        plane_row = layout.row()
        plane_row.scale_y = 1.3
        if has_shader_generation():
            plane_row.operator("text_texture.generate_plane", text="Create Plane", icon='MESH_GRID')
        else:
            plane_lock_row = plane_row.row()
            plane_lock_row.enabled = False
            plane_lock_row.label(text="🔒 Create Plane (Pro Only)", icon='LOCKED')
        
        # Preview Button - ALWAYS available (core functionality for all users)
        layout.separator(factor=0.5)
        preview_row = layout.row()
        preview_row.scale_y = 1.5
        preview_row.operator("text_texture.preview", text="Preview Texture", icon='HIDE_OFF')
        
        layout.separator(factor=0.6)
        draw_reset_button(layout)
        
        layout.separator(factor=1.2)
        
        # COLLAPSIBLE SECTIONS - FREE FEATURES FIRST
        
        # === FREE FEATURES ===
        
        # Font Settings Section (collapsed by default)
        font_section = draw_collapsible_header(layout, "expand_font_settings", "Font Settings", 'FONT_DATA')
        if font_section:
            pass
            draw_font_settings_section(font_section, props)
        
        # Positioning & Layout Section (collapsed by default) - FREE FEATURE moved to free group
        position_section = draw_collapsible_header(layout, "expand_positioning", "Positioning & Layout", 'ANCHOR_CENTER')
        if position_section:
            draw_positioning_section(position_section, props)
        
        # Colors Section (collapsed by default)
        colors_section = draw_collapsible_header(layout, "expand_colors", "Colors", 'COLOR')
        if colors_section:
            pass
            draw_colors_section(colors_section, props)
        
        # === PREMIUM FEATURES ===
        
        # Shader Section (collapsed by default) - ONLY OPTIONS, NOT THE BUTTON
        shader_header_row = layout.row(align=True)
        
        # Gray out header if locked and prevent expansion
        from ..utils.constants import has_shader_generation
        if not has_shader_generation():
            shader_header_row.enabled = False
            # Don't allow expansion for locked features
            shader_expanded = None
            # Show lock indicator instead of expandable header
            lock_header = shader_header_row.row()
            lock_header.label(text="Shader Options", icon='SETTINGS')
            lock_header.label(text="🔒 PRO", icon='LOCKED')
        else:
            shader_expanded = draw_collapsible_header(shader_header_row, "expand_shader", "Shader Options", 'SETTINGS')
        
        # Only show content if available and expanded
        if shader_expanded:
            draw_shader_options_only(shader_expanded, props)
        
        # Composition Section (collapsed by default)
        composition_section = draw_premium_collapsible_section(
            layout,
            "expand_composition",
            "Composition",
            'SEQ_PREVIEW',
            has_image_overlays
        )
        if composition_section:
            draw_composition_section(composition_section, props)
        
        
        # Stroke Section (collapsed by default) - Show with premium indicator
        stroke_header_row = layout.row(align=True)
        
        # Gray out header if locked and prevent expansion
        from ..utils.constants import has_stroke_effects
        if not has_stroke_effects():
            stroke_header_row.enabled = False
            # Don't allow expansion for locked features
            stroke_expanded = None
            # Show lock indicator instead of expandable header
            lock_header = stroke_header_row.row()
            lock_header.label(text="Stroke & Outlines", icon='MOD_OUTLINE')
            lock_header.label(text="🔒 PRO", icon='LOCKED')
        else:
            stroke_expanded = draw_collapsible_header(stroke_header_row, "expand_stroke", "Stroke & Outlines", 'MOD_OUTLINE')
        
        # Only show content if available and expanded
        if stroke_expanded:
            draw_stroke_section(stroke_expanded, props)
        
        # Shadow & Glow Section (collapsed by default) - Show with premium indicator
        shadow_glow_header_row = layout.row(align=True)
        
        # Gray out header if locked and prevent expansion
        from ..utils.constants import has_shadow_glow_effects
        if not has_shadow_glow_effects():
            shadow_glow_header_row.enabled = False
            # Don't allow expansion for locked features
            shadow_glow_expanded = None
            # Show lock indicator instead of expandable header
            lock_header = shadow_glow_header_row.row()
            lock_header.label(text="Shadow & Glow Effects", icon='SHADERFX')
            lock_header.label(text="🔒 PRO", icon='LOCKED')
        else:
            shadow_glow_expanded = draw_collapsible_header(shadow_glow_header_row, "expand_shadow_glow", "Shadow & Glow Effects", 'SHADERFX')
        
        # Only show content if available and expanded
        if shadow_glow_expanded:
            draw_shadow_glow_section(shadow_glow_expanded, props)
        
        # Blur Section (collapsed by default) - Show with premium indicator
        blur_header_row = layout.row(align=True)
        
        # Gray out header if locked and prevent expansion
        from ..utils.constants import has_blur_effects
        if not has_blur_effects():
            blur_header_row.enabled = False
            # Don't allow expansion for locked features
            blur_expanded = None
            # Show lock indicator instead of expandable header
            lock_header = blur_header_row.row()
            lock_header.label(text="Blur Effects", icon='MOD_SMOOTH')
            lock_header.label(text="🔒 PRO", icon='LOCKED')
        else:
            blur_expanded = draw_collapsible_header(blur_header_row, "expand_blur", "Blur Effects", 'MOD_SMOOTH')
        
        # Only show content if available and expanded
        if blur_expanded:
            draw_blur_section(blur_expanded, props)
        
        # Normal Maps Section (collapsed by default) - Show with premium indicator
        normal_header_row = layout.row(align=True)
        
        # Gray out header if locked and prevent expansion
        if not has_normal_maps():
            normal_header_row.enabled = False
            # Don't allow expansion for locked features
            normal_expanded = None
            # Show lock indicator instead of expandable header
            lock_header = normal_header_row.row()
            lock_header.label(text="Normal Maps", icon='TEXTURE')
            lock_header.label(text="🔒 PRO", icon='LOCKED')
        else:
            normal_expanded = draw_collapsible_header(normal_header_row, "expand_normal_maps", "Normal Maps", 'TEXTURE')
        
        # Only show content if available and expanded
        if normal_expanded:
            draw_normal_maps_section(normal_expanded, props)
        
        # Presets Section (collapsed by default) - Show with premium indicator
        presets_header_row = layout.row(align=True)
        
        # Gray out header if locked and prevent expansion
        if not has_presets():
            presets_header_row.enabled = False
            # Don't allow expansion for locked features
            presets_expanded = None
            # Show lock indicator instead of expandable header
            lock_header = presets_header_row.row()
            lock_header.label(text="Presets", icon='PRESET')
            lock_header.label(text="🔒 PRO", icon='LOCKED')
        else:
            presets_expanded = draw_collapsible_header(presets_header_row, "expand_presets", "Presets", 'PRESET')
        
        # Only show content if available and expanded
        if presets_expanded:
            draw_presets_section(presets_expanded, props)

class TEXT_TEXTURE_PT_panel_properties(Panel):
    pass
    """Properties Panel"""
    bl_label = "Text Texture Generator"
    bl_idname = "TEXT_TEXTURE_PT_panel_properties"
    bl_space_type = 'PROPERTIES'
    bl_region_type = 'WINDOW'
    bl_context = "material"
    bl_category = "Tool"
    
    def draw(self, context):
        pass
        layout = self.layout
        props = context.scene.text_texture_props
        
        # TOP LEVEL - Always Visible Controls
        
        # Text Input
        box = layout.box()
        box.label(text="Text:", icon='TEXT')
        draw_text_input_section(box, props)
        
        
        # Generate Button
        layout.separator(factor=0.5)
        draw_generate_button(layout)
        
        # CREATE SHADER BUTTON - WITH PROPER RESTRICTION
        layout.separator(factor=0.5)
        create_shader_row = layout.row()
        create_shader_row.scale_y = 1.5
        
        # Check if shader generation is available
        from ..utils.constants import has_shader_generation
        if has_shader_generation():
            create_shader_row.operator("text_texture.generate_shader", text="Create Shader", icon='MATERIAL')
        else:
            # Show locked shader button for free version
            lock_row = create_shader_row.row()
            lock_row.enabled = False
            lock_row.operator("text_texture.generate_shader", text="🔒 Create Shader (Pro Only)", icon='LOCKED')

        plane_row = layout.row()
        plane_row.scale_y = 1.3
        if has_shader_generation():
            plane_row.operator("text_texture.generate_plane", text="Create Plane", icon='MESH_GRID')
        else:
            plane_lock_row = plane_row.row()
            plane_lock_row.enabled = False
            plane_lock_row.label(text="🔒 Create Plane (Pro Only)", icon='LOCKED')
        
        # Preview Button - ALWAYS available (core functionality for all users)
        layout.separator(factor=0.5)
        preview_row = layout.row()
        preview_row.scale_y = 1.5
        preview_row.operator("text_texture.preview", text="Preview Texture", icon='HIDE_OFF')
        
        layout.separator(factor=0.6)
        draw_reset_button(layout)

        layout.separator(factor=1.2)
        
        # COLLAPSIBLE SECTIONS - FREE FEATURES FIRST
        
        # === FREE FEATURES ===
        
        # Font Settings Section (collapsed by default)
        font_section = draw_collapsible_header(layout, "expand_font_settings", "Font Settings", 'FONT_DATA')
        if font_section:
            pass
            draw_font_settings_section(font_section, props)
        
        # Positioning & Layout Section (collapsed by default) - FREE FEATURE moved to free group
        position_section = draw_collapsible_header(layout, "expand_positioning", "Positioning & Layout", 'ANCHOR_CENTER')
        if position_section:
            draw_positioning_section(position_section, props)
        
        # Colors Section (collapsed by default)
        colors_section = draw_collapsible_header(layout, "expand_colors", "Colors", 'COLOR')
        if colors_section:
            pass
            draw_colors_section(colors_section, props)
        
        # === PREMIUM FEATURES ===
        
        # Composition Section (collapsed by default)
        composition_section = draw_premium_collapsible_section(
            layout,
            "expand_composition",
            "Composition",
            'SEQ_PREVIEW',
            has_image_overlays
        )
        if composition_section:
            draw_composition_section(composition_section, props)
        
        
        # Stroke Section (collapsed by default) - Show with premium indicator
        stroke_header_row = layout.row(align=True)
        
        # Gray out header if locked and prevent expansion
        from ..utils.constants import has_stroke_effects
        if not has_stroke_effects():
            stroke_header_row.enabled = False
            # Don't allow expansion for locked features
            stroke_expanded = None
            # Show lock indicator instead of expandable header
            lock_header = stroke_header_row.row()
            lock_header.label(text="Stroke & Outlines", icon='MOD_OUTLINE')
            lock_header.label(text="🔒 PRO", icon='LOCKED')
        else:
            stroke_expanded = draw_collapsible_header(stroke_header_row, "expand_stroke", "Stroke & Outlines", 'MOD_OUTLINE')
        
        # Only show content if available and expanded
        if stroke_expanded:
            draw_stroke_section(stroke_expanded, props)
        
        # Shadow & Glow Section (collapsed by default) - Show with premium indicator
        shadow_glow_header_row = layout.row(align=True)
        
        # Gray out header if locked and prevent expansion
        from ..utils.constants import has_shadow_glow_effects
        if not has_shadow_glow_effects():
            shadow_glow_header_row.enabled = False
            # Don't allow expansion for locked features
            shadow_glow_expanded = None
            # Show lock indicator instead of expandable header
            lock_header = shadow_glow_header_row.row()
            lock_header.label(text="Shadow & Glow Effects", icon='SHADERFX')
            lock_header.label(text="🔒 PRO", icon='LOCKED')
        else:
            shadow_glow_expanded = draw_collapsible_header(shadow_glow_header_row, "expand_shadow_glow", "Shadow & Glow Effects", 'SHADERFX')
        
        # Only show content if available and expanded
        if shadow_glow_expanded:
            draw_shadow_glow_section(shadow_glow_expanded, props)
        
        # Blur Section (collapsed by default) - Show with premium indicator
        blur_header_row = layout.row(align=True)
        
        # Gray out header if locked and prevent expansion
        from ..utils.constants import has_blur_effects
        if not has_blur_effects():
            blur_header_row.enabled = False
            # Don't allow expansion for locked features
            blur_expanded = None
            # Show lock indicator instead of expandable header
            lock_header = blur_header_row.row()
            lock_header.label(text="Blur Effects", icon='MOD_SMOOTH')
            lock_header.label(text="🔒 PRO", icon='LOCKED')
        else:
            blur_expanded = draw_collapsible_header(blur_header_row, "expand_blur", "Blur Effects", 'MOD_SMOOTH')
        
        # Only show content if available and expanded
        if blur_expanded:
            draw_blur_section(blur_expanded, props)
        
        # Normal Maps Section (collapsed by default) - Show with premium indicator
        normal_header_row = layout.row(align=True)
        
        # Gray out header if locked and prevent expansion
        if not has_normal_maps():
            normal_header_row.enabled = False
            # Don't allow expansion for locked features
            normal_expanded = None
            # Show lock indicator instead of expandable header
            lock_header = normal_header_row.row()
            lock_header.label(text="Normal Maps", icon='TEXTURE')
            lock_header.label(text="🔒 PRO", icon='LOCKED')
        else:
            normal_expanded = draw_collapsible_header(normal_header_row, "expand_normal_maps", "Normal Maps", 'TEXTURE')
        
        # Only show content if available and expanded
        if normal_expanded:
            draw_normal_maps_section(normal_expanded, props)
        
        # Presets Section (collapsed by default) - Show with premium indicator
        presets_header_row = layout.row(align=True)
        
        # Gray out header if locked and prevent expansion
        if not has_presets():
            presets_header_row.enabled = False
            # Don't allow expansion for locked features
            presets_expanded = None
            # Show lock indicator instead of expandable header
            lock_header = presets_header_row.row()
            lock_header.label(text="Presets", icon='PRESET')
            lock_header.label(text="🔒 PRO", icon='LOCKED')
        else:
            presets_expanded = draw_collapsible_header(presets_header_row, "expand_presets", "Presets", 'PRESET')
        
        # Only show content if available and expanded
        if presets_expanded:
            draw_presets_section(presets_expanded, props)
