"""
HOLD Display - Terminal/TUI Rendering
═════════════════════════════════════════════════════════

ASCII arcade aesthetic with modern clarity.
Renders hold state for terminal interfaces.
"""

from typing import TYPE_CHECKING, Tuple

if TYPE_CHECKING:
    from cascade.hold.session import InferenceStep, HoldSession


class HoldDisplay:
    """
    Render hold state to terminal.
    
    ASCII arcade aesthetic with modern clarity.
    
    Usage:
        display = HoldDisplay(width=60)
        
        # Render a step
        print(display.render_step(step, session))
        
        # Render session stats
        print(display.render_stats(session))
    """
    
    # Box drawing characters
    TL = "╔"
    TR = "╗"
    BL = "╚"
    BR = "╝"
    H = "═"
    V = "║"
    
    # Progress bar
    FILLED = "█"
    PARTIAL = "░"
    
    def __init__(self, width: int = 60):
        self.width = width
    
    def render_step(self, step: 'InferenceStep', session: 'HoldSession') -> str:
        """Render a step to string."""
        lines = []
        w = self.width
        
        # Header
        lines.append(f"{self.TL}{self.H * (w-2)}{self.TR}")
        
        # Title bar
        state_str = f"[{session.state.value.upper()}]"
        combo_str = f"COMBO: {session.combo}" if session.combo > 0 else ""
        speed_str = ["MANUAL", "SLOW", "MED", "FAST", "!!!"][session.speed_level]
        
        title = f" STEP {step.step_index + 1} "
        padding = w - 4 - len(title) - len(state_str) - len(speed_str)
        lines.append(f"{self.V}{title}{' ' * max(0, padding)}{speed_str} {state_str}{self.V}")
        
        lines.append(f"{self.V}{self.H * (w-2)}{self.V}")
        
        # Context preview
        ctx_str = str(step.input_context)[:w-6]
        lines.append(f"{self.V} IN: {ctx_str:<{w-7}}{self.V}")
        
        lines.append(f"{self.V}{' ' * (w-2)}{self.V}")
        
        # Candidates
        lines.append(f"{self.V} {'CANDIDATES':<{w-4}}{self.V}")
        
        for i, cand in enumerate(step.candidates[:5]):
            key = "SPC" if i == 0 else str(i)
            val = str(cand['value'])[:20]
            prob = cand.get('probability', 0)
            bar_width = 20
            filled = int(prob * bar_width)
            bar = self.FILLED * filled + self.PARTIAL * (bar_width - filled)
            prob_str = f"{prob*100:>5.1f}%"
            
            line = f" [{key}] {val:<20} {bar} {prob_str}"
            lines.append(f"{self.V}{line:<{w-2}}{self.V}")
        
        lines.append(f"{self.V}{' ' * (w-2)}{self.V}")
        
        # Attention (if available)
        if step.attention_weights:
            lines.append(f"{self.V} {'ATTENTION':<{w-4}}{self.V}")
            attn_str = " ".join(
                f"{k}[{'█' * int(v*5)}]" 
                for k, v in list(step.attention_weights.items())[:5]
            )[:w-4]
            lines.append(f"{self.V} {attn_str:<{w-4}}{self.V}")
            lines.append(f"{self.V}{' ' * (w-2)}{self.V}")
        
        # Combo display
        if session.combo >= 5:
            combo_bar = "★" * min(session.combo // 5, 10)
            lines.append(f"{self.V} {combo_bar:^{w-4}}{self.V}")
        
        # Controls
        lines.append(f"{self.V}{self.H * (w-2)}{self.V}")
        controls = "[SPC]Accept [1-9]Override [←→]Navigate [+−]Speed"
        lines.append(f"{self.V} {controls:<{w-4}}{self.V}")
        
        # Footer
        lines.append(f"{self.BL}{self.H * (w-2)}{self.BR}")
        
        return "\n".join(lines)
    
    def render_stats(self, session: 'HoldSession') -> str:
        """Render session stats."""
        lines = []
        w = self.width
        
        lines.append(f"\n{'═' * w}")
        lines.append(f"{'SESSION COMPLETE':^{w}}")
        lines.append(f"{'═' * w}")
        lines.append(f"  Steps:     {session.total_steps}")
        lines.append(f"  Overrides: {session.human_overrides}")
        lines.append(f"  Max Combo: {session.max_combo}")
        lines.append(f"  Accuracy:  {session.correct_predictions}/{session.total_steps}")
        lines.append(f"{'═' * w}\n")
        
        return "\n".join(lines)
    
    def render_mini(self, step: 'InferenceStep', session: 'HoldSession') -> str:
        """Compact single-line render for inline display."""
        top = step.candidates[0] if step.candidates else {'value': '?', 'probability': 0}
        combo = f"x{session.combo}" if session.combo > 0 else ""
        return f"[{step.step_index}] {top['value']} ({top['probability']*100:.0f}%) {combo}"
    
    def render_decision_tree(
        self, 
        steps: list, 
        current_index: int,
        max_width: int = 80
    ) -> str:
        """
        Render a visual decision tree showing path taken.
        
        Shows the sequence of decisions with branches for overrides.
        """
        if not steps:
            return "No steps recorded."
        
        lines = []
        lines.append("Decision Path:")
        lines.append("─" * min(40, max_width))
        
        for i, step in enumerate(steps):
            prefix = "→" if i == current_index else " "
            override = "⚡" if step.was_override else "·"
            choice = str(step.chosen_value or step.top_choice)[:15]
            
            indent = "  " * min(i, 5)
            lines.append(f"{prefix} {indent}{override} [{i}] {choice}")
        
        return "\n".join(lines)
