from __future__ import annotations

import argparse

from .bootstrap_graph import build_bootstrap_graph
from .command_graph import build_command_graph
from .commands import execute_command, get_command, get_commands, render_command_index
from .direct_modes import run_deep_link, run_direct_connect
from .parity_audit import run_parity_audit
from .permissions import ToolPermissionContext
from .port_manifest import build_port_manifest
from .query_engine import QueryEngineConfig, QueryEnginePort, TurnResult
from .remote_runtime import run_remote_mode, run_ssh_mode, run_teleport_mode
from .runtime import PortRuntime
from .session_store import load_session
from .setup import run_setup
from .tool_pool import assemble_tool_pool
from .tools import execute_tool, get_tool, get_tools, render_tool_index


def build_parser() -> argparse.ArgumentParser:
    parser = argparse.ArgumentParser(description='Python porting workspace for the Albert-Code rewrite effort')
    subparsers = parser.add_subparsers(dest='command', required=True)
    subparsers.add_parser('summary', help='render a Markdown summary of the Python porting workspace')
    chat_parser = subparsers.add_parser('chat', help='start an interactive terminal chat session with Albert')
    chat_parser.add_argument('--lite', action='store_true', help='run in lite mode (no tool-calling loop)')
    subparsers.add_parser('manifest', help='print the current Python workspace manifest')
    subparsers.add_parser('parity-audit', help='compare the Python workspace against the local ignored TypeScript archive when available')
    subparsers.add_parser('setup-report', help='render the startup/prefetch setup report')
    subparsers.add_parser('command-graph', help='show command graph segmentation')
    subparsers.add_parser('tool-pool', help='show assembled tool pool with default settings')
    subparsers.add_parser('bootstrap-graph', help='show the mirrored bootstrap/runtime graph stages')
    list_parser = subparsers.add_parser('subsystems', help='list the current Python modules in the workspace')
    list_parser.add_argument('--limit', type=int, default=32)

    commands_parser = subparsers.add_parser('commands', help='list mirrored command entries from the archived snapshot')
    commands_parser.add_argument('--limit', type=int, default=20)
    commands_parser.add_argument('--query')
    commands_parser.add_argument('--no-plugin-commands', action='store_true')
    commands_parser.add_argument('--no-skill-commands', action='store_true')

    tools_parser = subparsers.add_parser('tools', help='list mirrored tool entries from the archived snapshot')
    tools_parser.add_argument('--limit', type=int, default=20)
    tools_parser.add_argument('--query')
    tools_parser.add_argument('--simple-mode', action='store_true')
    tools_parser.add_argument('--no-mcp', action='store_true')
    tools_parser.add_argument('--deny-tool', action='append', default=[])
    tools_parser.add_argument('--deny-prefix', action='append', default=[])

    route_parser = subparsers.add_parser('route', help='route a prompt across mirrored command/tool inventories')
    route_parser.add_argument('prompt')
    route_parser.add_argument('--limit', type=int, default=5)

    bootstrap_parser = subparsers.add_parser('bootstrap', help='build a runtime-style session report from the mirrored inventories')
    bootstrap_parser.add_argument('prompt')
    bootstrap_parser.add_argument('--limit', type=int, default=5)

    loop_parser = subparsers.add_parser('turn-loop', help='run a small stateful turn loop for the mirrored runtime')
    loop_parser.add_argument('prompt')
    loop_parser.add_argument('--limit', type=int, default=5)
    loop_parser.add_argument('--max-turns', type=int, default=3)
    loop_parser.add_argument('--structured-output', action='store_true')

    flush_parser = subparsers.add_parser('flush-transcript', help='persist and flush a temporary session transcript')
    flush_parser.add_argument('prompt')

    load_session_parser = subparsers.add_parser('load-session', help='load a previously persisted session')
    load_session_parser.add_argument('session_id')

    remote_parser = subparsers.add_parser('remote-mode', help='simulate remote-control runtime branching')
    remote_parser.add_argument('target')
    ssh_parser = subparsers.add_parser('ssh-mode', help='simulate SSH runtime branching')
    ssh_parser.add_argument('target')
    teleport_parser = subparsers.add_parser('teleport-mode', help='simulate teleport runtime branching')
    teleport_parser.add_argument('target')
    direct_parser = subparsers.add_parser('direct-connect-mode', help='simulate direct-connect runtime branching')
    direct_parser.add_argument('target')
    deep_link_parser = subparsers.add_parser('deep-link-mode', help='simulate deep-link runtime branching')
    deep_link_parser.add_argument('target')

    show_command = subparsers.add_parser('show-command', help='show one mirrored command entry by exact name')
    show_command.add_argument('name')
    show_tool = subparsers.add_parser('show-tool', help='show one mirrored tool entry by exact name')
    show_tool.add_argument('name')

    exec_command_parser = subparsers.add_parser('exec-command', help='execute a mirrored command shim by exact name')
    exec_command_parser.add_argument('name')
    exec_command_parser.add_argument('prompt')

    exec_tool_parser = subparsers.add_parser('exec-tool', help='execute a mirrored tool shim by exact name')
    exec_tool_parser.add_argument('name')
    exec_tool_parser.add_argument('payload')
    return parser


def main(argv: list[str] | None = None) -> int:
    parser = build_parser()
    args = parser.parse_args(argv)
    manifest = build_port_manifest()
    if args.command == 'chat':
        engine = QueryEnginePort.from_workspace()
        mode_title = "ALBERT-CHAT" if args.lite else "ALBERT-CODE"
        mode_desc = "Cognitive Interface for RFI-IRFOS" if args.lite else "Sovereign Actuator for RFI-IRFOS"
        mode_color = "cyan" if args.lite else "green"

        if args.lite:
            # Disable tool loop and change identity to Chat
            engine.config = QueryEngineConfig(max_turns=1, model=engine.config.model, lite_mode=True)
        
        HEADER = r"""
 █████  ██      ██████  ███████ ██████  ████████ 
██   ██ ██      ██   ██ ██      ██   ██    ██    
███████ ██      ██████  █████   ██████     ██    
██   ██ ██      ██   ██ ██      ██   ██    ██    
██   ██ ███████ ██████  ███████ ██   ██    ██    
        """
        try:
            from rich.console import Console
            from rich.panel import Panel
            from rich.markdown import Markdown
            console = Console()
            console.print(f"[bold {mode_color}]{HEADER}[/bold {mode_color}]")
            console.print(Panel(f"[bold {mode_color}]{mode_title}[/bold {mode_color}] [dim]v2.0[/dim]\n[cyan]{mode_desc}[/cyan]\n[yellow]Session: {engine.session_id}[/yellow]", border_style=mode_color))
            if not args.lite:
                console.print("[dim]Type [bold]/help[/bold] for commands or [bold]exit[/bold] to quit.[/dim]")
            else:
                console.print("[dim]Quick-chat mode active. Type [bold]exit[/bold] to quit.[/dim]")
        except ImportError:
            print(HEADER)
            print(f"--- {mode_title} (Session: {engine.session_id}) ---")

        while True:
            try:
                console.print("\n[bold yellow]simeon:[/bold yellow] ", end="")
                user_input = input()
                if user_input.lower() in {"exit", "quit", "bye"}:
                    engine.persist_session()
                    console.print("[bold red]✓ Session persisted. Goodbye.[/bold red]")
                    break
                
                if not user_input.strip():
                    continue

                # Slash Commands
                if user_input.startswith("/"):
                    parts = user_input.split()
                    cmd = parts[0].lower()
                    
                    if cmd == "/help":
                        console.print("[bold cyan]Available Commands:[/bold cyan]")
                        console.print("  [bold]/tools[/bold]    - List available actuators")
                        console.print("  [bold]/health[/bold]   - System telemetry")
                        console.print("  [bold]/clear[/bold]    - Clear terminal")
                        console.print("  [bold]/memory[/bold]   - View recent vault entries")
                        console.print("  [bold]/makefile[/bold] - Quick file creation (Usage: /makefile <path> <content>)")
                        console.print("  [bold]/bash[/bold]     - Quick shell command (Usage: /bash <command>)")
                        console.print("  [bold]/exit[/bold]     - Persist and quit")
                        continue
                    
                    if cmd == "/tools":
                        console.print(render_tool_index())
                        continue
                    
                    if cmd == "/health":
                        from .tools import get_system_health
                        console.print(Panel(get_system_health(), title="System Health", border_style="blue"))
                        continue
                    
                    if cmd == "/clear":
                        console.clear()
                        console.print(f"[bold green]{HEADER}[/bold green]")
                        continue
                    
                    if cmd == "/memory":
                        from .tools import retrieve_memory
                        console.print(Panel(retrieve_memory(""), title="Vault Memory", border_style="magenta"))
                        continue

                    if cmd == "/makefile":
                        if len(parts) < 3:
                            console.print("[red]Usage: /makefile <path> <content>[/red]")
                        else:
                            path = parts[1]
                            content = " ".join(parts[2:])
                            from .tools import create_file
                            console.print(create_file(path, content))
                        continue

                    if cmd == "/bash":
                        if len(parts) < 2:
                            console.print("[red]Usage: /bash <command>[/red]")
                        else:
                            command = " ".join(parts[1:])
                            from .tools import execute_bash
                            console.print(Panel(execute_bash(command), title=f"Bash: {command}", border_style="yellow"))
                        continue

                console.print("[bold cyan]albert:[/bold cyan] ", end="", highlight=False)
                result = engine.submit_message(
                    user_input,
                    on_stream=lambda piece: print(piece, end="", flush=True),
                )
                print()  # newline after stream ends

            except KeyboardInterrupt:
                engine.persist_session()
                print("\n✓ Session persisted. Goodbye.")
                break
            except Exception as e:
                print(f"Error: {e}")
        return 0

    if args.command == 'summary':
        print(QueryEnginePort(manifest).render_summary())
        return 0
    if args.command == 'manifest':
        print(manifest.to_markdown())
        return 0
    if args.command == 'parity-audit':
        print(run_parity_audit().to_markdown())
        return 0
    if args.command == 'setup-report':
        print(run_setup().as_markdown())
        return 0
    if args.command == 'command-graph':
        print(build_command_graph().as_markdown())
        return 0
    if args.command == 'tool-pool':
        print(assemble_tool_pool().as_markdown())
        return 0
    if args.command == 'bootstrap-graph':
        print(build_bootstrap_graph().as_markdown())
        return 0
    if args.command == 'subsystems':
        for subsystem in manifest.top_level_modules[: args.limit]:
            print(f'{subsystem.name}\t{subsystem.file_count}\t{subsystem.notes}')
        return 0
    if args.command == 'commands':
        if args.query:
            print(render_command_index(limit=args.limit, query=args.query))
        else:
            commands = get_commands(include_plugin_commands=not args.no_plugin_commands, include_skill_commands=not args.no_skill_commands)
            output_lines = [f'Command entries: {len(commands)}', '']
            output_lines.extend(f'- {module.name} — {module.source_hint}' for module in commands[: args.limit])
            print('\n'.join(output_lines))
        return 0
    if args.command == 'tools':
        if args.query:
            print(render_tool_index(limit=args.limit, query=args.query))
        else:
            permission_context = ToolPermissionContext.from_iterables(args.deny_tool, args.deny_prefix)
            tools = get_tools(simple_mode=args.simple_mode, include_mcp=not args.no_mcp, permission_context=permission_context)
            output_lines = [f'Tool entries: {len(tools)}', '']
            output_lines.extend(f'- {module.name} — {module.source_hint}' for module in tools[: args.limit])
            print('\n'.join(output_lines))
        return 0
    if args.command == 'route':
        matches = PortRuntime().route_prompt(args.prompt, limit=args.limit)
        if not matches:
            print('No mirrored command/tool matches found.')
            return 0
        for match in matches:
            print(f'{match.kind}\t{match.name}\t{match.score}\t{match.source_hint}')
        return 0
    if args.command == 'bootstrap':
        print(PortRuntime().bootstrap_session(args.prompt, limit=args.limit).as_markdown())
        return 0
    if args.command == 'turn-loop':
        results = PortRuntime().run_turn_loop(args.prompt, limit=args.limit, max_turns=args.max_turns, structured_output=args.structured_output)
        for idx, result in enumerate(results, start=1):
            print(f'## Turn {idx}')
            print(result.output)
            print(f'stop_reason={result.stop_reason}')
        return 0
    if args.command == 'flush-transcript':
        engine = QueryEnginePort.from_workspace()
        engine.submit_message(args.prompt)
        path = engine.persist_session()
        print(path)
        print(f'flushed={engine.transcript_store.flushed}')
        return 0
    if args.command == 'load-session':
        session = load_session(args.session_id)
        print(f'{session.session_id}\n{len(session.messages)} messages\nin={session.input_tokens} out={session.output_tokens}')
        return 0
    if args.command == 'remote-mode':
        print(run_remote_mode(args.target).as_text())
        return 0
    if args.command == 'ssh-mode':
        print(run_ssh_mode(args.target).as_text())
        return 0
    if args.command == 'teleport-mode':
        print(run_teleport_mode(args.target).as_text())
        return 0
    if args.command == 'direct-connect-mode':
        print(run_direct_connect(args.target).as_text())
        return 0
    if args.command == 'deep-link-mode':
        print(run_deep_link(args.target).as_text())
        return 0
    if args.command == 'show-command':
        module = get_command(args.name)
        if module is None:
            print(f'Command not found: {args.name}')
            return 1
        print('\n'.join([module.name, module.source_hint, module.responsibility]))
        return 0
    if args.command == 'show-tool':
        module = get_tool(args.name)
        if module is None:
            print(f'Tool not found: {args.name}')
            return 1
        print('\n'.join([module.name, module.source_hint, module.responsibility]))
        return 0
    if args.command == 'exec-command':
        result = execute_command(args.name, args.prompt)
        print(result.message)
        return 0 if result.handled else 1
    if args.command == 'exec-tool':
        result = execute_tool(args.name, args.payload)
        print(result.message)
        return 0 if result.handled else 1
    parser.error(f'unknown command: {args.command}')
    return 2


if __name__ == '__main__':
    raise SystemExit(main())
