"""
Widget presenter implementation for advanced terminal display.

This presenter uses Node.js widgets for rich terminal UI capabilities,
providing the most advanced display options inspired by Claudia.
"""

import json
import subprocess
import tempfile
from pathlib import Path
from typing import Any, Dict, List, Optional, Union, Callable

from .base import BasePresenter, ProgressContext


class WidgetProgressContext(ProgressContext):
    """Widget-specific progress context using Node.js widgets."""
    
    def __init__(self, presenter: 'WidgetPresenter', task_name: str, total: Optional[int] = None):
        super().__init__(presenter, task_name, total)
        self.widget_id = None
    
    def start(self) -> None:
        """Start the progress indicator."""
        self.widget_id = self.presenter._create_progress_widget(self.task_name, self.total)
    
    def update(self, advance: int = 1, description: Optional[str] = None) -> None:
        """Update the progress indicator."""
        self.current += advance
        if self.widget_id:
            self.presenter._update_progress_widget(self.widget_id, self.current, description)
    
    def finish(self) -> None:
        """Finish and hide the progress indicator."""
        self.completed = True
        if self.widget_id:
            self.presenter._finish_progress_widget(self.widget_id)


class WidgetPresenter(BasePresenter):
    """Widget presenter using Node.js advanced terminal widgets."""
    
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.theme = kwargs.get('theme', 'dark')
        self.layout = kwargs.get('layout', 'vertical')
        self.node_available = self._check_node()
        
        if not self.node_available:
            print("⚠️  Node.js not available. Widget presenter requires Node.js.")
            print("   Falling back to console presenter.")
    
    def _check_node(self) -> bool:
        """Check if Node.js is available."""
        try:
            result = subprocess.run(['node', '--version'], 
                                  capture_output=True, text=True)
            return result.returncode == 0
        except FileNotFoundError:
            return False
    
    def _run_widget_script(self, script: str) -> Optional[str]:
        """Run a Node.js widget script."""
        if not self.node_available:
            return None
        
        with tempfile.NamedTemporaryFile(mode='w', suffix='.js', delete=False) as f:
            f.write(script)
            temp_path = f.name
        
        try:
            result = subprocess.run(['node', temp_path], 
                                  capture_output=True, text=True)
            return result.stdout if result.returncode == 0 else None
        finally:
            Path(temp_path).unlink(missing_ok=True)
    
    def _create_widget_script(self, widget_type: str, options: Dict[str, Any]) -> str:
        """Create a Node.js script for widget display."""
        options_json = json.dumps(options)
        
        return f"""
const path = require('path');
const widgetPath = path.join(__dirname, 'lib', 'widgets');
const {{ WidgetManager }} = require(widgetPath);

const manager = new WidgetManager({{
    theme: '{self.theme}',
    layout: '{self.layout}'
}});

const options = {options_json};
const widgetType = '{widget_type}';

// Create and render widget based on type
switch (widgetType) {{
    case 'info':
    case 'error':
    case 'success':
    case 'warning':
        const msgWidget = manager.createWidget('message', 'toolResult', {{
            title: options.title || widgetType.toUpperCase(),
            toolType: 'generic'
        }});
        msgWidget.setResult({{ 
            message: options.message,
            status: widgetType === 'error' ? 'error' : 
                    widgetType === 'warning' ? 'warning' : 'success'
        }});
        console.log(manager.render());
        break;
        
    case 'code':
        const codeWidget = manager.showCode(
            options.code,
            options.language || 'javascript',
            {{
                title: options.title || 'Code',
                lineNumbers: options.lineNumbers !== false,
                highlightLine: options.highlightLine
            }}
        );
        console.log(manager.render());
        break;
        
    case 'tree':
        const treeWidget = manager.showFileTree(
            options.tree,
            {{
                title: options.title || 'File Tree',
                expandedPaths: options.expandedPaths || [],
                showIcons: options.showIcons !== false
            }}
        );
        console.log(manager.render());
        break;
        
    case 'stream':
        const streamWidget = manager.showStreamingResponse(
            options.content,
            {{
                title: options.title || 'Response',
                stream: options.stream !== false,
                typingSpeed: options.typingSpeed || 30
            }}
        );
        console.log(manager.render());
        break;
        
    case 'header':
        console.log('\\n' + '='.repeat(60));
        console.log(options.title);
        if (options.subtitle) {{
            console.log(options.subtitle);
        }}
        console.log('='.repeat(60) + '\\n');
        break;
        
    default:
        console.log(options.message || '');
}}
"""
    
    # Status message methods
    def show_info(self, message: str, **kwargs) -> None:
        """Display an informational message."""
        script = self._create_widget_script('info', {
            'message': message,
            'title': kwargs.get('title', 'Information')
        })
        output = self._run_widget_script(script)
        if output:
            print(output, end='')
        else:
            print(f"ℹ️  {message}")
    
    def show_error(self, message: str, **kwargs) -> None:
        """Display an error message."""
        script = self._create_widget_script('error', {
            'message': message,
            'title': kwargs.get('title', 'Error')
        })
        output = self._run_widget_script(script)
        if output:
            print(output, end='')
        else:
            print(f"❌ {message}")
    
    def show_success(self, message: str, **kwargs) -> None:
        """Display a success message."""
        script = self._create_widget_script('success', {
            'message': message,
            'title': kwargs.get('title', 'Success')
        })
        output = self._run_widget_script(script)
        if output:
            print(output, end='')
        else:
            print(f"✅ {message}")
    
    def show_warning(self, message: str, **kwargs) -> None:
        """Display a warning message."""
        script = self._create_widget_script('warning', {
            'message': message,
            'title': kwargs.get('title', 'Warning')
        })
        output = self._run_widget_script(script)
        if output:
            print(output, end='')
        else:
            print(f"⚠️  {message}")
    
    # Formatting methods
    def show_header(self, title: str, **kwargs) -> None:
        """Display a section header."""
        script = self._create_widget_script('header', {
            'title': title,
            'subtitle': kwargs.get('subtitle')
        })
        output = self._run_widget_script(script)
        if output:
            print(output, end='')
        else:
            print(f"\n{'=' * 50}")
            print(title.upper())
            print('=' * 50)
    
    def show_code(self, code: str, language: Optional[str] = None, **kwargs) -> None:
        """Display code with syntax highlighting."""
        script = self._create_widget_script('code', {
            'code': code,
            'language': language or 'text',
            'title': kwargs.get('title'),
            'lineNumbers': kwargs.get('line_numbers', True),
            'highlightLine': kwargs.get('highlight_line')
        })
        output = self._run_widget_script(script)
        if output:
            print(output, end='')
        else:
            # Fallback
            print(f"```{language or ''}")
            print(code)
            print("```")
    
    def show_tree(self, tree_data: Any, **kwargs) -> None:
        """Display hierarchical tree structure."""
        # Convert tree data to widget format
        if isinstance(tree_data, dict):
            tree_dict = tree_data
        else:
            # Convert other formats to dict
            tree_dict = {'root': str(tree_data)}
        
        script = self._create_widget_script('tree', {
            'tree': tree_dict,
            'title': kwargs.get('title', 'Tree Structure'),
            'expandedPaths': kwargs.get('expanded_paths', []),
            'showIcons': kwargs.get('show_icons', True)
        })
        output = self._run_widget_script(script)
        if output:
            print(output, end='')
        else:
            # Fallback
            print(str(tree_data))
    
    def stream_content(self, content_generator: Union[Callable[[], str], Any], **kwargs) -> None:
        """Display streaming content."""
        try:
            # Get full content
            if callable(content_generator):
                content = content_generator()
            else:
                content = str(content_generator)
            
            script = self._create_widget_script('stream', {
                'content': content,
                'title': kwargs.get('title', 'Streaming Response'),
                'stream': True,
                'typingSpeed': kwargs.get('typing_speed', 30)
            })
            output = self._run_widget_script(script)
            if output:
                print(output, end='')
            else:
                # Fallback
                print(content)
                
        except Exception as e:
            self.show_error(f"Streaming error: {e}")
    
    def show_progress(self, task_name: str, total: Optional[int] = None, **kwargs) -> ProgressContext:
        """Create and return a progress context."""
        return WidgetProgressContext(self, task_name, total)
    
    def _create_progress_widget(self, task_name: str, total: Optional[int]) -> str:
        """Create a progress widget and return its ID."""
        # For now, return a simple ID
        # In a full implementation, this would create an actual widget
        return f"progress_{id(task_name)}"
    
    def _update_progress_widget(self, widget_id: str, current: int, description: Optional[str]) -> None:
        """Update a progress widget."""
        # In a full implementation, this would update the widget
        if description:
            print(f"\r{description}: {current}", end='', flush=True)
    
    def _finish_progress_widget(self, widget_id: str) -> None:
        """Finish and remove a progress widget."""
        print()  # New line after progress
    
    # Interactive methods
    def confirm_action(self, message: str, **kwargs) -> bool:
        """Prompt user for confirmation."""
        # For widgets, we'll use a simple input for now
        # In a full implementation, this would use an interactive widget
        response = input(f"{message} (y/N): ").strip().lower()
        return response in ['y', 'yes']
    
    # Utility methods
    def clear_screen(self) -> None:
        """Clear the screen."""
        import os
        os.system('clear' if os.name != 'nt' else 'cls')
    
    def set_title(self, title: str) -> None:
        """Set the terminal title."""
        print(f"\033]0;{title}\007", end='', flush=True)