"""
Help text and documentation for terminal client commands.

Provides detailed, formatted help text for all REPL commands
with usage examples and option descriptions.

Author: Claude
Date: 2025-10-27
"""
from typing import Dict
from rich.console import Console
from rich.table import Table
from rich.panel import Panel
from rich.markdown import Markdown
from rich import box

console = Console()


class HelpFormatter:
    """Format and display help text for commands."""

    @staticmethod
    def show_command_help(command_name: str, help_data: Dict) -> None:
        """
        Display detailed help for a specific command.

        Args:
            command_name: Name of the command
            help_data: Dictionary with help information
                {
                    'summary': 'Brief description',
                    'usage': 'command [OPTIONS]',
                    'options': [
                        {'name': '--option', 'type': 'TYPE', 'desc': 'Description'}
                    ],
                    'examples': ['example 1', 'example 2']
                }
        """
        # Build help text
        help_text = []

        # Summary
        help_text.append(f"**{command_name}** - {help_data.get('summary', 'No description')}")
        help_text.append("")

        # Usage
        if 'usage' in help_data:
            help_text.append("**USAGE:**")
            help_text.append(f"  {help_data['usage']}")
            help_text.append("")

        # Display in panel
        if help_text:
            md = Markdown("\n".join(help_text[:3]))  # Just summary and usage
            panel = Panel(
                md,
                title=f"[bold cyan]Help: {command_name}[/bold cyan]",
                border_style="cyan",
                box=box.ROUNDED
            )
            console.print(panel)
            console.print()

        # Options
        if 'options' in help_data and help_data['options']:
            console.print("[bold cyan]OPTIONS:[/bold cyan]")

            # Create options table
            table = Table(box=box.SIMPLE, show_header=False, padding=(0, 2))
            table.add_column("Option", style="cyan", no_wrap=True)
            table.add_column("Type", style="yellow")
            table.add_column("Description", style="white")

            for opt in help_data['options']:
                table.add_row(
                    opt['name'],
                    opt.get('type', ''),
                    opt.get('desc', '')
                )

            console.print(table)
            console.print()

        # Examples
        if 'examples' in help_data and help_data['examples']:
            console.print("[bold cyan]EXAMPLES:[/bold cyan]")
            for example in help_data['examples']:
                console.print(f"  {example}")
            console.print()

        # Notes
        if 'notes' in help_data:
            console.print(f"[dim]{help_data['notes']}[/dim]")
            console.print()

    @staticmethod
    def show_command_list() -> None:
        """Display list of all available commands."""
        console.print("\n[bold cyan]Available Commands:[/bold cyan]\n")

        # Game Management
        console.print("[bold yellow]Game Management:[/bold yellow]")
        console.print("  new_game      Create a new game with test lineups and start it")
        console.print("  list_games    List all games in state manager")
        console.print("  use_game      Switch to a different game")
        console.print("  status        Display current game state")
        console.print("  box_score     Display box score")
        console.print()

        # Gameplay
        console.print("[bold yellow]Gameplay:[/bold yellow]")
        console.print("  defensive       Submit defensive decision")
        console.print("  offensive       Submit offensive decision")
        console.print("  resolve         Resolve the current play")
        console.print("  resolve_with    Resolve with a specific outcome (testing)")
        console.print("  quick_play      Auto-play multiple plays")
        console.print()

        # Testing
        console.print("[bold yellow]Testing & Development:[/bold yellow]")
        console.print("  list_outcomes   Show all available PlayOutcome values")
        console.print("  test_location   Test hit location distribution")
        console.print("  rollback        Roll back the last N plays")
        console.print()

        # X-Check Testing (Dice Systems)
        console.print("[bold yellow]X-Check Testing:[/bold yellow]")
        console.print("  roll_jump       Roll jump dice for stolen base testing")
        console.print("  test_jump       Test jump roll distribution")
        console.print("  roll_fielding   Roll fielding check dice")
        console.print("  test_fielding   Test fielding roll distribution")
        console.print()

        # Interrupt Plays
        console.print("[bold yellow]Interrupt Plays:[/bold yellow]")
        console.print("  force_wild_pitch    Force a wild pitch interrupt play")
        console.print("  force_passed_ball   Force a passed ball interrupt play")
        console.print()

        # Utilities
        console.print("[bold yellow]Utilities:[/bold yellow]")
        console.print("  config        Show configuration")
        console.print("  clear         Clear the screen")
        console.print("  help          Show help for commands")
        console.print("  quit/exit     Exit the REPL")
        console.print()

        console.print("[dim]Type 'help <command>' for detailed information.[/dim]")
        console.print("[dim]Use TAB for auto-completion of commands and options.[/dim]\n")


# Detailed help data for each command
HELP_DATA = {
    'new_game': {
        'summary': 'Create a new game with test lineups and start it immediately',
        'usage': 'new_game [--league LEAGUE] [--home-team ID] [--away-team ID]',
        'options': [
            {
                'name': '--league',
                'type': 'sba|pd',
                'desc': 'League type (default: sba)'
            },
            {
                'name': '--home-team',
                'type': 'INT',
                'desc': 'Home team ID (default: 1)'
            },
            {
                'name': '--away-team',
                'type': 'INT',
                'desc': 'Away team ID (default: 2)'
            }
        ],
        'examples': [
            'new_game',
            'new_game --league pd',
            'new_game --league sba --home-team 5 --away-team 3'
        ]
    },

    'defensive': {
        'summary': 'Submit defensive decision for the current play',
        'usage': 'defensive [--alignment TYPE] [--infield DEPTH] [--outfield DEPTH] [--hold BASES]',
        'options': [
            {
                'name': '--alignment',
                'type': 'STRING',
                'desc': 'Defensive alignment: normal, shifted_left, shifted_right, extreme_shift (default: normal)'
            },
            {
                'name': '--infield',
                'type': 'STRING',
                'desc': 'Infield depth: in, normal, back, double_play (default: normal)'
            },
            {
                'name': '--outfield',
                'type': 'STRING',
                'desc': 'Outfield depth: in, normal, back (default: normal)'
            },
            {
                'name': '--hold',
                'type': 'LIST',
                'desc': 'Comma-separated bases to hold runners: 1,2,3 (default: none)'
            }
        ],
        'examples': [
            'defensive',
            'defensive --alignment shifted_left',
            'defensive --infield double_play --hold 1,3',
            'defensive --alignment extreme_shift --infield back --outfield back'
        ]
    },

    'offensive': {
        'summary': 'Submit offensive decision for the current play',
        'usage': 'offensive [--approach TYPE] [--steal BASES] [--hit-run] [--bunt]',
        'options': [
            {
                'name': '--approach',
                'type': 'STRING',
                'desc': 'Batting approach: normal, contact, power, patient (default: normal)'
            },
            {
                'name': '--steal',
                'type': 'LIST',
                'desc': 'Comma-separated bases to steal: 2,3 (default: none)'
            },
            {
                'name': '--hit-run',
                'type': 'FLAG',
                'desc': 'Execute hit-and-run play (default: false)'
            },
            {
                'name': '--bunt',
                'type': 'FLAG',
                'desc': 'Attempt bunt (default: false)'
            }
        ],
        'examples': [
            'offensive',
            'offensive --approach power',
            'offensive --steal 2',
            'offensive --steal 2,3 --hit-run',
            'offensive --approach contact --bunt'
        ]
    },

    'resolve': {
        'summary': 'Resolve the current play using submitted decisions',
        'usage': 'resolve',
        'options': [],
        'examples': [
            'resolve'
        ],
        'notes': 'Both defensive and offensive decisions must be submitted before resolving.'
    },

    'list_outcomes': {
        'summary': 'Display all available PlayOutcome values for manual outcome testing',
        'usage': 'list_outcomes',
        'options': [],
        'examples': [
            'list_outcomes'
        ],
        'notes': 'Shows a categorized table of all play outcomes. Use these values with resolve_with command.'
    },

    'resolve_with': {
        'summary': 'Resolve current play with a specific outcome (bypassing dice rolls)',
        'usage': 'resolve_with <OUTCOME>\n               resolve_with x-check <POSITION> [<RESULT>[+<ERROR>]]',
        'options': [
            {
                'name': 'OUTCOME',
                'type': 'STRING',
                'desc': 'PlayOutcome enum value. Use list_outcomes to see all available values.'
            },
            {
                'name': 'POSITION',
                'type': 'P|C|1B|2B|3B|SS|LF|CF|RF',
                'desc': 'For x-check: defensive position to test (required)'
            },
            {
                'name': 'RESULT',
                'type': 'G1|G2|G3|F1|F2|F3|SI1|SI2|DO2|DO3|TR3|FO|PO',
                'desc': 'For x-check: force specific converted result (optional)'
            },
            {
                'name': 'ERROR',
                'type': 'NO|E1|E2|E3|RP',
                'desc': 'For x-check: force specific error result (optional, default: NO)'
            }
        ],
        'examples': [
            'resolve_with single_1',
            'resolve_with homerun',
            'resolve_with groundball_a',
            'resolve_with double_uncapped',
            'resolve_with strikeout',
            'resolve_with x-check SS            # Random X-Check to shortstop',
            'resolve_with x-check LF DO2        # Force double to LF, no error',
            'resolve_with x-check 2B G2+E1      # Force groundout to 2B with E1',
            'resolve_with x-check SS SI2+E2     # Force single to SS with E2',
            'resolve_with x-check LF FO+RP      # Force flyout to LF with rare play'
        ],
        'notes': 'Experimental feature for testing specific scenarios without random dice rolls. X-Check mode uses full defense tables and error charts with actual player ratings. When RESULT+ERROR are specified, table lookups are bypassed for precise testing of specific outcomes.'
    },

    'quick_play': {
        'summary': 'Auto-play multiple plays with default decisions',
        'usage': 'quick_play [COUNT]',
        'options': [
            {
                'name': 'COUNT',
                'type': 'INT',
                'desc': 'Number of plays to execute (default: 1). Positional argument.'
            }
        ],
        'examples': [
            'quick_play',
            'quick_play 10',
            'quick_play 27     # Play roughly 3 innings',
            'quick_play 100    # Play full game quickly'
        ]
    },

    'status': {
        'summary': 'Display current game state',
        'usage': 'status',
        'options': [],
        'examples': [
            'status'
        ]
    },

    'box_score': {
        'summary': 'Display box score for the current game',
        'usage': 'box_score',
        'options': [],
        'examples': [
            'box_score'
        ]
    },

    'list_games': {
        'summary': 'List all games currently loaded in state manager',
        'usage': 'list_games',
        'options': [],
        'examples': [
            'list_games'
        ]
    },

    'use_game': {
        'summary': 'Switch to a different game',
        'usage': 'use_game <GAME_ID>',
        'options': [
            {
                'name': 'GAME_ID',
                'type': 'UUID',
                'desc': 'UUID of the game to switch to. Positional argument.'
            }
        ],
        'examples': [
            'use_game a1b2c3d4-e5f6-7890-abcd-ef1234567890',
            'use_game <TAB>    # Use tab completion to see available games'
        ]
    },

    'config': {
        'summary': 'Show terminal client configuration',
        'usage': 'config',
        'options': [],
        'examples': [
            'config'
        ]
    },

    'clear': {
        'summary': 'Clear the screen',
        'usage': 'clear',
        'options': [],
        'examples': [
            'clear'
        ]
    },

    # X-Check Testing Commands
    'roll_jump': {
        'summary': 'Roll jump dice for stolen base testing',
        'usage': 'roll_jump [LEAGUE]',
        'options': [
            {
                'name': 'LEAGUE',
                'type': 'sba|pd',
                'desc': 'League type (default: sba)'
            }
        ],
        'examples': [
            'roll_jump          # Roll for SBA league',
            'roll_jump pd       # Roll for PD league'
        ],
        'notes': 'Components: 1d20 check (1=pickoff, 2=balk, 3+=normal), 2d6 jump total'
    },

    'test_jump': {
        'summary': 'Test jump roll distribution statistics',
        'usage': 'test_jump [COUNT] [LEAGUE]',
        'options': [
            {
                'name': 'COUNT',
                'type': 'integer',
                'desc': 'Number of rolls to test (default: 10)'
            },
            {
                'name': 'LEAGUE',
                'type': 'sba|pd',
                'desc': 'League type (default: sba)'
            }
        ],
        'examples': [
            'test_jump              # 10 rolls for SBA',
            'test_jump 100          # 100 rolls for SBA',
            'test_jump 50 pd        # 50 rolls for PD'
        ],
        'notes': 'Shows pickoff/balk/normal frequency and 2d6 distribution'
    },

    'roll_fielding': {
        'summary': 'Roll fielding check dice for X-Check defensive plays',
        'usage': 'roll_fielding <POSITION> [LEAGUE]',
        'options': [
            {
                'name': 'POSITION',
                'type': 'P|C|1B|2B|3B|SS|LF|CF|RF',
                'desc': 'Fielding position (required)'
            },
            {
                'name': 'LEAGUE',
                'type': 'sba|pd',
                'desc': 'League type (default: sba)'
            }
        ],
        'examples': [
            'roll_fielding SS        # Roll for shortstop (SBA)',
            'roll_fielding P pd      # Roll for pitcher (PD)',
            'roll_fielding CF        # Roll for center field'
        ],
        'notes': 'Components: 1d20 range, 3d6 error total, d100/special rare play check'
    },

    'test_fielding': {
        'summary': 'Test fielding roll distribution for a position',
        'usage': 'test_fielding <POSITION> [COUNT] [LEAGUE]',
        'options': [
            {
                'name': 'POSITION',
                'type': 'P|C|1B|2B|3B|SS|LF|CF|RF',
                'desc': 'Fielding position (required)'
            },
            {
                'name': 'COUNT',
                'type': 'integer',
                'desc': 'Number of rolls (default: 10)'
            },
            {
                'name': 'LEAGUE',
                'type': 'sba|pd',
                'desc': 'League type (default: sba)'
            }
        ],
        'examples': [
            'test_fielding SS           # 10 rolls for shortstop',
            'test_fielding 2B 100       # 100 rolls for second base',
            'test_fielding CF 50 pd     # 50 rolls for center field (PD)'
        ],
        'notes': 'Shows rare play frequency, average range/error, and distribution stats'
    },

    'test_location': {
        'summary': 'Test hit location distribution for an outcome',
        'usage': 'test_location <OUTCOME> [HANDEDNESS] [COUNT]',
        'options': [
            {
                'name': 'OUTCOME',
                'type': 'PlayOutcome',
                'desc': 'PlayOutcome enum value (e.g., groundball_c)'
            },
            {
                'name': 'HANDEDNESS',
                'type': 'L|R',
                'desc': 'Batter handedness (default: R)'
            },
            {
                'name': 'COUNT',
                'type': 'integer',
                'desc': 'Number of samples (default: 100)'
            }
        ],
        'examples': [
            'test_location groundball_c',
            'test_location groundball_c L',
            'test_location flyout_b R 200'
        ],
        'notes': 'Shows distribution of hit locations based on pull rates'
    },

    'rollback': {
        'summary': 'Roll back the last N plays',
        'usage': 'rollback <NUM_PLAYS>',
        'options': [
            {
                'name': 'NUM_PLAYS',
                'type': 'integer',
                'desc': 'Number of plays to roll back (must be > 0)'
            }
        ],
        'examples': [
            'rollback 1      # Undo the last play',
            'rollback 3      # Undo the last 3 plays',
            'rollback 5      # Undo the last 5 plays'
        ],
        'notes': 'Deletes plays from database and reconstructs state by replaying'
    },

    'force_wild_pitch': {
        'summary': 'Force a wild pitch interrupt play',
        'usage': 'force_wild_pitch',
        'options': [],
        'examples': [
            'force_wild_pitch    # Runner on 2nd advances to 3rd'
        ],
        'notes': 'Advances all runners one base. This is an interrupt play (pa=0)'
    },

    'force_passed_ball': {
        'summary': 'Force a passed ball interrupt play',
        'usage': 'force_passed_ball',
        'options': [],
        'examples': [
            'force_passed_ball   # Runner on 1st advances to 2nd'
        ],
        'notes': 'Advances all runners one base. This is an interrupt play (pa=0)'
    }
}


def get_help_text(command: str) -> Dict:
    """
    Get help data for a command.

    Args:
        command: Command name

    Returns:
        Help data dictionary or empty dict if not found
    """
    return HELP_DATA.get(command, {})


def show_help(command: str = None) -> None:
    """
    Show help for a command or list all commands.

    Args:
        command: Command name or None for command list
    """
    if command:
        help_data = get_help_text(command)
        if help_data:
            HelpFormatter.show_command_help(command, help_data)
        else:
            console.print(f"[yellow]No help available for '{command}'[/yellow]")
            console.print("[dim]Type 'help' to see all available commands.[/dim]")
    else:
        HelpFormatter.show_command_list()
