#!/usr/bin/env python3
"""
Textual DOM Inspector - Analyze and debug Textual app widget trees
"""

import json
import sys
from pathlib import Path
from typing import Dict, Any, List

def inspect_textual_app(app_instance) -> Dict[str, Any]:
    """
    Inspect a running Textual app and return detailed DOM information
    """
    
    def widget_to_dict(widget) -> Dict[str, Any]:
        """Convert a widget to a dictionary representation"""
        widget_info = {
            'type': widget.__class__.__name__,
            'id': getattr(widget, 'id', None),
            'classes': list(getattr(widget, 'classes', [])),
            'styles': {},
            'size': {
                'width': getattr(getattr(widget, 'size', None), 'width', 0) if hasattr(widget, 'size') else 0,
                'height': getattr(getattr(widget, 'size', None), 'height', 0) if hasattr(widget, 'size') else 0
            },
            'position': {
                'x': getattr(getattr(widget, 'offset', None), 'x', 0) if hasattr(widget, 'offset') else 0,
                'y': getattr(getattr(widget, 'offset', None), 'y', 0) if hasattr(widget, 'offset') else 0
            },
            'visible': getattr(widget, 'visible', True),
            'has_focus': getattr(widget, 'has_focus', False),
            'children': []
        }
        
        # Extract key styles
        if hasattr(widget, 'styles'):
            styles = widget.styles
            widget_info['styles'] = {
                'display': str(getattr(styles, 'display', 'block')),
                'height': str(getattr(styles, 'height', 'auto')),
                'width': str(getattr(styles, 'width', 'auto')),
                'margin': str(getattr(styles, 'margin', '0')),
                'padding': str(getattr(styles, 'padding', '0')),
                'background': str(getattr(styles, 'background', 'transparent')),
            }
        
        # Add widget-specific properties
        if hasattr(widget, 'label'):
            widget_info['label'] = str(widget.label)
        if hasattr(widget, 'text'):
            widget_info['text'] = str(widget.text)[:100]  # Truncate long text
        if hasattr(widget, 'rows'):
            widget_info['row_count'] = len(widget.rows) if widget.rows else 0
        if hasattr(widget, 'columns'):
            widget_info['column_count'] = len(widget.columns) if widget.columns else 0
            
        # Recursively process children
        if hasattr(widget, 'children'):
            for child in widget.children:
                widget_info['children'].append(widget_to_dict(child))
                
        return widget_info
    
    # Start with the app screen
    if hasattr(app_instance, 'screen'):
        return {
            'app_title': getattr(app_instance, 'title', 'Unknown App'),
            'screen_stack_size': len(getattr(app_instance, 'screen_stack', [])),
            'current_screen': widget_to_dict(app_instance.screen)
        }
    else:
        return {'error': 'App instance does not have accessible screen'}

def print_widget_tree(widget_data: Dict[str, Any], indent: int = 0) -> None:
    """Print a formatted widget tree"""
    prefix = "  " * indent
    widget_type = widget_data.get('type', 'Unknown')
    widget_id = widget_data.get('id', '')
    widget_classes = widget_data.get('classes', [])
    
    # Format the line
    line = f"{prefix}📦 {widget_type}"
    if widget_id:
        line += f" #{widget_id}"
    if widget_classes:
        line += f" .{'.'.join(widget_classes)}"
        
    # Add key properties
    if 'label' in widget_data:
        line += f" [label: {widget_data['label']}]"
    if 'row_count' in widget_data:
        line += f" [rows: {widget_data['row_count']}]"
    if 'column_count' in widget_data:
        line += f" [cols: {widget_data['column_count']}]"
        
    size = widget_data.get('size', {})
    if size.get('width') or size.get('height'):
        line += f" [{size.get('width', 0)}x{size.get('height', 0)}]"
        
    if not widget_data.get('visible', True):
        line += " [HIDDEN]"
    if widget_data.get('has_focus', False):
        line += " [FOCUSED]"
        
    print(line)
    
    # Print children
    for child in widget_data.get('children', []):
        print_widget_tree(child, indent + 1)

def analyze_layout_issues(widget_data: Dict[str, Any]) -> List[str]:
    """Analyze potential layout issues"""
    issues = []
    
    def check_widget(widget, path=""):
        current_path = f"{path}/{widget.get('type', 'Unknown')}"
        if widget.get('id'):
            current_path += f"#{widget['id']}"
            
        # Check for zero-sized widgets that should have content
        size = widget.get('size', {})
        if size.get('width') == 0 or size.get('height') == 0:
            if widget.get('type') in ['Button', 'DataTable', 'Static'] and 'label' in widget:
                issues.append(f"Zero-sized widget with content: {current_path}")
                
        # Check for invisible widgets with focus
        if not widget.get('visible', True) and widget.get('has_focus', False):
            issues.append(f"Invisible widget has focus: {current_path}")
            
        # Check for overlapping positioning (basic check)
        styles = widget.get('styles', {})
        if 'absolute' in str(styles.get('position', '')):
            # Could add position conflict detection here
            pass
            
        # Recursively check children
        for child in widget.get('children', []):
            check_widget(child, current_path)
    
    check_widget(widget_data.get('current_screen', {}))
    return issues

def create_textual_debug_snippet() -> str:
    """Create a code snippet to add to Textual apps for debugging"""
    return '''
# Add this to your Textual app for debugging
def debug_widget_tree(self):
    """Debug method to inspect widget tree"""
    from textual_inspector import inspect_textual_app, print_widget_tree
    
    data = inspect_textual_app(self)
    print("🔍 TEXTUAL APP INSPECTION")
    print("=" * 50)
    print_widget_tree(data.get('current_screen', {}))
    
    # You can call this from anywhere in your app:
    # self.debug_widget_tree()
    
def debug_focused_widget(self):
    """Debug method to find focused widget"""
    focused = self.focused
    if focused:
        print(f"🎯 Focused widget: {focused.__class__.__name__}")
        if hasattr(focused, 'id'):
            print(f"   ID: {focused.id}")
        if hasattr(focused, 'classes'):
            print(f"   Classes: {list(focused.classes)}")
    else:
        print("🎯 No widget has focus")
'''

def main():
    print("🔍 Textual DOM Inspector")
    print("=" * 50)
    print("This tool helps debug Textual applications.")
    print("\nTo use with your app, add this import:")
    print("from textual_inspector import inspect_textual_app, print_widget_tree")
    print("\nThen in your app:")
    print("data = inspect_textual_app(self)")
    print("print_widget_tree(data.get('current_screen', {}))")
    print("\n" + "=" * 50)
    print("\n📝 Debug snippet:")
    print(create_textual_debug_snippet())

if __name__ == "__main__":
    main()