#include "cli/cli.h"

#include <iostream>
#include <optional>

#include "absl/flags/flag.h"
#include "absl/flags/declare.h"
#include "absl/strings/ascii.h"
#include "absl/strings/match.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
#include "absl/strings/str_join.h"

#include "app/core/asar_wrapper.h"
#include "app/rom.h"
#include "cli/z3ed_ascii_logo.h"
#include "cli/tui/tui.h"
#include "app/snes.h"
#include "util/macro.h"

// Define additional z3ed-specific flags
ABSL_DECLARE_FLAG(std::string, rom);
ABSL_DECLARE_FLAG(bool, quiet);
ABSL_DECLARE_FLAG(std::string, ai_provider);
ABSL_DECLARE_FLAG(std::string, ai_model);
ABSL_DECLARE_FLAG(std::string, gemini_api_key);
ABSL_DECLARE_FLAG(std::string, ollama_host);
ABSL_DECLARE_FLAG(std::string, prompt_version);
ABSL_DECLARE_FLAG(bool, use_function_calling);

namespace yaze {
namespace cli {

ModernCLI::ModernCLI() {
  SetupCommands();
}


void ModernCLI::SetupCommands() {
    commands_["patch apply-asar"] = {
      .name = "patch apply-asar",
      .description = "Apply Asar 65816 assembly patch to ROM",
      .usage = "z3ed patch apply-asar <patch.asm> [--rom=<rom_file>] [--output=<output_file>]",
      .handler = [this](const std::vector<std::string>& args) -> absl::Status {
        return HandleAsarPatchCommand(args);
      }
    };

    commands_["patch apply-bps"] = {
      .name = "patch apply-bps", 
      .description = "Apply BPS patch to ROM",
      .usage = "z3ed patch apply-bps <patch.bps> [--rom=<rom_file>] [--output=<output_file>]",
      .handler = [this](const std::vector<std::string>& args) -> absl::Status {
        return HandleBpsPatchCommand(args);
      }
    };

    commands_["patch extract-symbols"] = {
      .name = "patch extract-symbols",
      .description = "Extract symbols from assembly file",
      .usage = "z3ed patch extract-symbols <patch.asm>",
      .handler = [this](const std::vector<std::string>& args) -> absl::Status {
        return HandleExtractSymbolsCommand(args);
      }
    };

    commands_["rom info"] = {
      .name = "rom info",
      .description = "Show ROM information",
      .usage = "z3ed rom info [--rom=<rom_file>]",
      .handler = [this](const std::vector<std::string>& args) -> absl::Status {
        return HandleRomInfoCommand(args);
      }
    };

    commands_["agent"] = {
      .name = "agent",
      .description = "🤖 AI-Powered Conversational Agent for ROM Inspection\n"
                     "   Interact naturally with Zelda3 ROM data using embedded labels\n"
                     "   ✨ Features: Natural language queries, automatic label lookup, context-aware responses",
      .usage = "\n"
               "╔═══════════════════════════════════════════════════════════════════════════╗\n"
               "║                        🤖 AI AGENT COMMANDS                              ║\n"
               "╚═══════════════════════════════════════════════════════════════════════════╝\n"
               "\n"
               "💬 CONVERSATIONAL MODE (Recommended for testing):\n"
               "  z3ed agent test-conversation [--rom=<path>] [--verbose] [--file=<json>]\n"
               "    → Interactive AI testing with all embedded Zelda3 labels\n"
               "    → Ask about rooms, sprites, entrances, items naturally\n"
               "    → Example: 'What sprites are in room 5?' or 'List all dungeons'\n"
               "\n"
               "💡 SIMPLE CHAT MODE (Multiple input methods):\n"
               "  # Single message\n"
               "  z3ed agent simple-chat \"<your question>\" --rom=<path>\n"
               "  \n"
               "  # Interactive session\n"
               "  z3ed agent simple-chat --rom=<path>\n"
               "  \n"
               "  # Piped input\n"
               "  echo \"What is room 5?\" | z3ed agent simple-chat --rom=<path>\n"
               "  \n"
               "  # Batch file (one question per line)\n"
               "  z3ed agent simple-chat --file=questions.txt --rom=<path>\n"
               "\n"
               "🎯 ADVANCED CHAT MODE:\n"
               "  z3ed agent chat \"<prompt>\" [--host=<host>] [--port=<port>]\n"
               "    → Full conversational AI with Ollama/Gemini\n"
               "    → Supports multi-turn conversations\n"
               "\n"
               "📊 TEST MANAGEMENT:\n"
               "  z3ed agent test run --prompt \"<description>\" [--timeout=<sec>]\n"
               "  z3ed agent test status --test-id=<id> [--follow]\n"
               "  z3ed agent test list [--category=<name>] [--status=<state>]\n"
               "  z3ed agent test results --test-id=<id> [--format=yaml|json]\n"
               "  z3ed agent test suite <run|validate|create>\n"
               "\n"
               "🔍 OTHER COMMANDS:\n"
               "  z3ed agent gui discover [--window=<name>] [--type=<widget>]\n"
               "  z3ed agent describe [--resource=<name>] [--format=json|yaml]\n"
               "\n"
               "🏰 EMBEDDED LABELS (Always Available):\n"
               "  • 296+ room names       • 256 sprite names      • 133 entrance names\n"
               "  • 100 item names        • 160 overworld maps    • 48 music tracks\n"
               "  • 60 tile types         • 26 overlord names     • 32 graphics sheets\n"
               "\n"
               "📚 No separate labels file needed - all names built into z3ed!\n",
      .handler = [this](const std::vector<std::string>& args) -> absl::Status {
        return HandleAgentCommand(args);
      }
    };

    commands_["chat"] = {
      .name = "chat",
      .description =
          "Unified chat entrypoint with text, markdown, or JSON output",
      .usage =
          "z3ed chat [--mode=simple|gui|test] [--format=text|markdown|json|compact]"
          " [--prompt \"<message>\"] [--file=<questions.txt>] [--quiet]",
      .handler = [this](const std::vector<std::string>& args) -> absl::Status {
        return HandleChatEntryCommand(args);
      }
    };

    commands_["proposal"] = {
      .name = "proposal",
      .description = "Review and manage AI-generated change proposals",
      .usage =
          "z3ed proposal <run|list|diff|show|accept|commit|revert> [options]",
      .handler = [this](const std::vector<std::string>& args) -> absl::Status {
        return HandleProposalCommand(args);
      }
    };

    commands_["collab"] = {
      .name = "collab",
      .description = "🌐 Collaboration Server Management\n"
                     "   Launch and manage the WebSocket collaboration server for networked sessions",
      .usage = "\n"
               "╔═══════════════════════════════════════════════════════════════════════════╗\n"
               "║                 🌐 COLLABORATION SERVER COMMANDS                          ║\n"
               "╚═══════════════════════════════════════════════════════════════════════════╝\n"
               "\n"
               "🚀 SERVER MANAGEMENT:\n"
               "  z3ed collab start [--port=<port>]\n"
               "    → Start the WebSocket collaboration server\n"
               "    → Default port: 8765\n"
               "    → Server will be accessible at ws://localhost:<port>\n"
               "\n"
               "📊 SERVER STATUS:\n"
               "  z3ed collab status\n"
               "    → Check if collaboration server is running\n"
               "    → Show active sessions and participants\n"
               "\n"
               "💡 USAGE:\n"
               "  1. Start server: z3ed collab start\n"
               "  2. In YAZE GUI: Debug → Agent Chat\n"
               "  3. Select 'Network' mode and connect to ws://localhost:8765\n"
               "  4. Host or join a session to collaborate!\n",
      .handler = [this](const std::vector<std::string>& args) -> absl::Status {
        return HandleCollabCommand(args);
      }
    };

    commands_["widget"] = {
      .name = "widget",
      .description = "Discover GUI widgets exposed through automation APIs",
      .usage = "z3ed widget discover [--window=<name>] [--type=<widget>]",
      .handler = [this](const std::vector<std::string>& args) -> absl::Status {
        return HandleWidgetCommand(args);
      }
    };

    commands_["widget discover"] = {
      .name = "widget discover",
      .description = "Inspect UI widgets using the automation service",
      .usage =
          "z3ed widget discover [--window=<name>] [--type=<widget>]"
          " [--format=text|json]",
      .handler = [this](const std::vector<std::string>& args) -> absl::Status {
        return HandleWidgetCommand(args);
      }
    };

    commands_["project build"] = {
      .name = "project build",
      .description = "Build the project and create a new ROM file",
      .usage = "z3ed project build",
      .handler = [this](const std::vector<std::string>& args) -> absl::Status {
        return HandleProjectBuildCommand(args);
      }
    };

    commands_["project init"] = {
      .name = "project init",
      .description = "Initialize a new z3ed project",
      .usage = "z3ed project init <project_name>",
      .handler = [this](const std::vector<std::string>& args) -> absl::Status {
        return HandleProjectInitCommand(args);
      }
    };

    commands_["rom generate-golden"] = {
      .name = "rom generate-golden",
      .description = "Generate a golden file from a ROM for regression testing",
      .usage = "z3ed rom generate-golden <rom_file> <golden_file>",
      .handler = [this](const std::vector<std::string>& args) -> absl::Status {
        return HandleRomGenerateGoldenCommand(args);
      }
    };

    commands_["rom diff"] = {
      .name = "rom diff",
      .description = "Compare two ROM files and show the differences",
      .usage = "z3ed rom diff <rom_a> <rom_b>",
      .handler = [this](const std::vector<std::string>& args) -> absl::Status {
        return HandleRomDiffCommand(args);
      }
    };

    commands_["rom validate"] = {
      .name = "rom validate",
      .description = "Validate the ROM file",
      .usage = "z3ed rom validate [--rom=<rom_file>]",
      .handler = [this](const std::vector<std::string>& args) -> absl::Status {
        return HandleRomValidateCommand(args);
      }
    };

    commands_["dungeon export"] = {
      .name = "dungeon export",
      .description = "Export dungeon data to a file",
      .usage = "z3ed dungeon export <room_id> --to <file>",
      .handler = [this](const std::vector<std::string>& args) -> absl::Status {
        return HandleDungeonExportCommand(args);
      }
    };

    commands_["dungeon list-objects"] = {
      .name = "dungeon list-objects",
      .description = "List all objects in a dungeon room",
      .usage = "z3ed dungeon list-objects <room_id>",
      .handler = [this](const std::vector<std::string>& args) -> absl::Status {
        return HandleDungeonListObjectsCommand(args);
      }
    };

    commands_["gfx export-sheet"] = {
      .name = "gfx export-sheet",
      .description = "Export a graphics sheet to a file",
      .usage = "z3ed gfx export-sheet <sheet_id> --to <file>",
      .handler = [this](const std::vector<std::string>& args) -> absl::Status {
        return HandleGfxExportCommand(args);
      }
    };

    commands_["gfx import-sheet"] = {
      .name = "gfx import-sheet",
      .description = "Import a graphics sheet from a file",
      .usage = "z3ed gfx import-sheet <sheet_id> --from <file>",
      .handler = [this](const std::vector<std::string>& args) -> absl::Status {
        return HandleGfxImportCommand(args);
      }
    };

    commands_["command-palette"] = {
      .name = "command-palette",
      .description = "Show the command palette",
      .usage = "z3ed command-palette",
      .handler = [this](const std::vector<std::string>& args) -> absl::Status {
        return HandleCommandPaletteCommand(args);
      }
    };

    commands_["palette"] = {
      .name = "palette",
      .description = "Manage palette data (export/import)",
      .usage = "z3ed palette <export|import> [options]",
      .handler = [this](const std::vector<std::string>& args) -> absl::Status {
        return HandlePaletteCommand(args);
      }
    };

    commands_["palette export"] = {
      .name = "palette export",
      .description = "Export a palette to a file",
      .usage = "z3ed palette export --group <group> --id <id> --to <file>",
      .handler = [this](const std::vector<std::string>& args) -> absl::Status {
        return HandlePaletteExportCommand(args);
      }
    };

    commands_["palette import"] = {
      .name = "palette import",
      .description = "Import a palette from a file",
      .usage = "z3ed palette import --group <group> --id <id> --from <file>",
      .handler = [this](const std::vector<std::string>& args) -> absl::Status {
        return HandlePaletteImportCommand(args);
      }
    };

    commands_["overworld get-tile"] = {
        .name = "overworld get-tile",
        .description = "Get a tile from the overworld",
        .usage = "z3ed overworld get-tile --map <map_id> --x <x> --y <y>",
        .handler = [this](const std::vector<std::string>& args) -> absl::Status {
            return HandleOverworldGetTileCommand(args);
        }
    };

  commands_["overworld find-tile"] = {
    .name = "overworld find-tile",
    .description = "Search overworld maps for a tile ID",
    .usage = "z3ed overworld find-tile --tile <tile_id> [--map <map_id>] [--world light|dark|special] [--format json|text]",
    .handler = [this](const std::vector<std::string>& args) -> absl::Status {
      return HandleOverworldFindTileCommand(args);
    }
  };

    commands_["overworld describe-map"] = {
      .name = "overworld describe-map",
      .description = "Summarize metadata for an overworld map",
      .usage = "z3ed overworld describe-map --map <map_id> [--format json|text]",
      .handler = [this](const std::vector<std::string>& args) -> absl::Status {
        return HandleOverworldDescribeMapCommand(args);
      }
    };

    commands_["overworld list-warps"] = {
      .name = "overworld list-warps",
      .description = "List overworld entrances and holes with coordinates",
      .usage = "z3ed overworld list-warps [--map <map_id>] [--world light|dark|special] [--type entrance|hole|exit|all] [--format json|text]",
      .handler = [this](const std::vector<std::string>& args) -> absl::Status {
        return HandleOverworldListWarpsCommand(args);
      }
    };

    commands_["overworld set-tile"] = {
        .name = "overworld set-tile",
        .description = "Set a tile in the overworld",
        .usage = "z3ed overworld set-tile --map <map_id> --x <x> --y <y> --tile <tile_id>",
        .handler = [this](const std::vector<std::string>& args) -> absl::Status {
            return HandleOverworldSetTileCommand(args);
        }
    };

    commands_["overworld select-rect"] = {
        .name = "overworld select-rect",
        .description = "Select a rectangular region of tiles",
        .usage = "z3ed overworld select-rect --map <map_id> --x1 <x1> --y1 <y1> --x2 <x2> --y2 <y2>",
        .handler = [this](const std::vector<std::string>& args) -> absl::Status {
            return HandleOverworldSelectRectCommand(args);
        }
    };

    commands_["overworld scroll-to"] = {
        .name = "overworld scroll-to",
        .description = "Scroll canvas to show specific tile",
        .usage = "z3ed overworld scroll-to --map <map_id> --x <x> --y <y> [--center]",
        .handler = [this](const std::vector<std::string>& args) -> absl::Status {
            return HandleOverworldScrollToCommand(args);
        }
    };

    commands_["overworld set-zoom"] = {
        .name = "overworld set-zoom",
        .description = "Set canvas zoom level",
        .usage = "z3ed overworld set-zoom --zoom <level> (0.25-4.0)",
        .handler = [this](const std::vector<std::string>& args) -> absl::Status {
            return HandleOverworldSetZoomCommand(args);
        }
    };

    commands_["overworld get-visible-region"] = {
        .name = "overworld get-visible-region",
        .description = "Get currently visible tile region",
        .usage = "z3ed overworld get-visible-region --map <map_id> [--format json|text]",
        .handler = [this](const std::vector<std::string>& args) -> absl::Status {
            return HandleOverworldGetVisibleRegionCommand(args);
        }
    };

    commands_["sprite create"] = {
        .name = "sprite create",
        .description = "Create a new sprite",
        .usage = "z3ed sprite create --name <name> [options]",
        .handler = [this](const std::vector<std::string>& args) -> absl::Status {
            return HandleSpriteCreateCommand(args);
        }
    };
}

void ModernCLI::ShowHelp() {
    std::cout << GetColoredLogo() << std::endl;
    std::cout << std::endl;
    std::cout << "\033[1m\033[36mUSAGE:\033[0m" << std::endl;
    std::cout << "  z3ed [options] <command> [arguments]" << std::endl;
    std::cout << std::endl;
    
    std::cout << "\033[1m\033[36mGLOBAL OPTIONS:\033[0m" << std::endl;
    std::cout << "  --tui              Launch interactive Text User Interface" << std::endl;
    std::cout << "  --rom=<file>       Specify ROM file path" << std::endl;
    std::cout << "  --verbose, -v      Show detailed debug output" << std::endl;
    std::cout << "  --version          Show version information" << std::endl;
    std::cout << "  --help, -h         Show this help message" << std::endl;
    std::cout << std::endl;
    
    // Categorize commands
    std::cout << "\033[1m\033[36mCOMMANDS:\033[0m" << std::endl;
    std::cout << std::endl;
    
  std::cout << "  \033[1m🤖 AI Agent\033[0m" << std::endl;
  std::cout << "    chat                  Unified chat entrypoint (text/json/markdown)" << std::endl;
  std::cout << "    agent simple-chat     Natural language ROM queries" << std::endl;
  std::cout << "    agent test-conversation  Interactive testing mode" << std::endl;
  std::cout << "    \033[90m→ z3ed help chat, z3ed help agent\033[0m" << std::endl;
    std::cout << std::endl;

  std::cout << "  \033[1m🧠 Proposals\033[0m" << std::endl;
  std::cout << "    proposal run          Execute AI-driven sandbox plan" << std::endl;
  std::cout << "    proposal list         Show pending proposals" << std::endl;
  std::cout << "    proposal diff         Review latest sandbox diff" << std::endl;
  std::cout << "    proposal accept       Apply sandbox changes" << std::endl;
  std::cout << "    \033[90m→ z3ed help proposal\033[0m" << std::endl;
  std::cout << std::endl;

  std::cout << "  \033[1m🪟 GUI Automation\033[0m" << std::endl;
  std::cout << "    widget discover       Inspect GUI widgets via automation" << std::endl;
  std::cout << "    \033[90m→ z3ed help widget\033[0m" << std::endl;
  std::cout << std::endl;
    
    std::cout << "  \033[1m🔧 ROM Patching\033[0m" << std::endl;
    std::cout << "    patch apply-asar      Apply Asar 65816 assembly patch" << std::endl;
    std::cout << "    patch apply-bps       Apply BPS binary patch" << std::endl;
    std::cout << "    patch extract-symbols Extract symbols from assembly" << std::endl;
    std::cout << "    \033[90m→ z3ed help patch\033[0m" << std::endl;
    std::cout << std::endl;
    
    std::cout << "  \033[1m📦 ROM Operations\033[0m" << std::endl;
    std::cout << "    rom info              Display ROM information" << std::endl;
    std::cout << "    rom diff              Compare two ROM files" << std::endl;
    std::cout << "    rom generate-golden   Create golden test file" << std::endl;
    std::cout << "    \033[90m→ z3ed help rom\033[0m" << std::endl;
    std::cout << std::endl;
    
    std::cout << "  \033[1m🗺️  Overworld\033[0m" << std::endl;
    std::cout << "    overworld get-tile    Get tile at coordinates" << std::endl;
    std::cout << "    overworld set-tile    Place tile at coordinates" << std::endl;
    std::cout << "    overworld find-tile   Search for tile occurrences" << std::endl;
    std::cout << "    overworld describe-map  Show map metadata" << std::endl;
    std::cout << "    overworld list-warps  List entrances and exits" << std::endl;
    std::cout << "    \033[90m→ z3ed help overworld\033[0m" << std::endl;
    std::cout << std::endl;
    
    std::cout << "  \033[1m🏰 Dungeon\033[0m" << std::endl;
    std::cout << "    dungeon export        Export dungeon data" << std::endl;
    std::cout << "    dungeon import        Import dungeon data" << std::endl;
    std::cout << "    \033[90m→ z3ed help dungeon\033[0m" << std::endl;
    std::cout << std::endl;
    
    std::cout << "  \033[1m🎨 Graphics\033[0m" << std::endl;
    std::cout << "    gfx export-sheet      Export graphics sheet" << std::endl;
    std::cout << "    gfx import-sheet      Import graphics sheet" << std::endl;
    std::cout << "    palette export        Export palette data" << std::endl;
    std::cout << "    palette import        Import palette data" << std::endl;
    std::cout << "    \033[90m→ z3ed help gfx, z3ed help palette\033[0m" << std::endl;
    std::cout << std::endl;
    
    std::cout << "\033[1m\033[36mQUICK START:\033[0m" << std::endl;
    std::cout << "  z3ed --tui" << std::endl;
  std::cout << "  z3ed chat \"What is room 5?\" --rom=zelda3.sfc --format=markdown" << std::endl;
    std::cout << "  z3ed patch apply-asar patch.asm --rom=zelda3.sfc" << std::endl;
    std::cout << std::endl;
    
    std::cout << "\033[90mFor detailed help: z3ed help <category>\033[0m" << std::endl;
}

void ModernCLI::PrintTopLevelHelp() const {
  const_cast<ModernCLI*>(this)->ShowHelp();
}

void ModernCLI::PrintCategoryHelp(const std::string& category) const {
  const_cast<ModernCLI*>(this)->ShowCategoryHelp(category);
}

void ModernCLI::PrintCommandSummary() const {
  const_cast<ModernCLI*>(this)->ShowCommandSummary();
}

void ModernCLI::ShowCategoryHelp(const std::string& category) {
  std::cout << GetColoredLogo() << std::endl;
  std::cout << std::endl;
  
  if (category == "agent") {
    std::cout << "\033[1m\033[36m🤖 AI AGENT COMMANDS\033[0m" << std::endl;
    std::cout << std::endl;
    std::cout << "\033[1mDESCRIPTION:\033[0m" << std::endl;
    std::cout << "  Natural language interface for ROM inspection using embedded labels." << std::endl;
    std::cout << "  Query rooms, sprites, entrances, and game data conversationally." << std::endl;
    std::cout << std::endl;
    std::cout << "\033[1mCOMMANDS:\033[0m" << std::endl;
    std::cout << std::endl;
    std::cout << "  \033[1magent simple-chat\033[0m [\"<question>\"]" << std::endl;
    std::cout << "    Single-shot or interactive chat mode" << std::endl;
    std::cout << "    Options: --rom=<file>, --verbose" << std::endl;
    std::cout << "    Examples:" << std::endl;
    std::cout << "      z3ed agent simple-chat \"What sprites are in room 5?\" --rom=zelda3.sfc" << std::endl;
    std::cout << "      echo \"List all dungeons\" | z3ed agent simple-chat --rom=zelda3.sfc" << std::endl;
    std::cout << std::endl;
    std::cout << "  \033[1magent test-conversation\033[0m" << std::endl;
    std::cout << "    Interactive testing mode with full context" << std::endl;
    std::cout << "    Options: --rom=<file>, --verbose, --file=<json>" << std::endl;
    std::cout << std::endl;
    std::cout << "  \033[1magent chat\033[0m \"<prompt>\"" << std::endl;
    std::cout << "    Advanced multi-turn conversation mode" << std::endl;
    std::cout << "    Options: --host=<host>, --port=<port>" << std::endl;
    std::cout << std::endl;
    std::cout << "\033[1mTIPS:\033[0m" << std::endl;
    std::cout << "  • Use --verbose to see detailed API calls and responses" << std::endl;
    std::cout << "  • Set GEMINI_API_KEY environment variable for Gemini" << std::endl;
    std::cout << "  • Use --ai_provider=gemini or --ai_provider=ollama" << std::endl;
    std::cout << std::endl;
    
  } else if (category == "chat") {
    std::cout << "\033[1m\033[36m💬 CHAT ENTRYPOINT\033[0m" << std::endl;
    std::cout << std::endl;
    std::cout << "\033[1mDESCRIPTION:\033[0m" << std::endl;
    std::cout << "  Launch the embedded agent in text, markdown, or JSON-friendly modes." << std::endl;
    std::cout << std::endl;
    std::cout << "\033[1mMODES:\033[0m" << std::endl;
    std::cout << "  chat --mode=simple        Quick REPL with --format=text|markdown|json|compact" << std::endl;
    std::cout << "  chat --mode=batch --file=F   Run prompts from file (one per line)" << std::endl;
    std::cout << "  chat --mode=gui            Launch the full FTXUI conversation experience" << std::endl;
    std::cout << "  chat --mode=test           Execute scripted agent conversation for QA" << std::endl;
    std::cout << std::endl;
    std::cout << "\033[1mOPTIONS:\033[0m" << std::endl;
    std::cout << "  --format=text|markdown|json|compact    Control response formatting" << std::endl;
    std::cout << "  --prompt \"<msg>\"                  Send a single message and exit" << std::endl;
    std::cout << "  --file questions.txt                  Batch mode input" << std::endl;
    std::cout << "  --quiet                                Suppress extra banners" << std::endl;
    std::cout << std::endl;

  } else if (category == "proposal") {
    std::cout << "\033[1m\033[36m🧠 PROPOSAL WORKFLOWS\033[0m" << std::endl;
    std::cout << std::endl;
    std::cout << "\033[1mCOMMANDS:\033[0m" << std::endl;
    std::cout << "  proposal run --prompt \"<desc>\"        Plan and execute changes in sandbox" << std::endl;
    std::cout << "  proposal list                          Show pending proposals" << std::endl;
    std::cout << "  proposal diff [--proposal-id=X]        Inspect latest diff/log" << std::endl;
    std::cout << "  proposal accept --proposal-id=X        Apply sandbox changes to main ROM" << std::endl;
    std::cout << "  proposal commit | proposal revert      Persist or undo sandbox changes" << std::endl;
    std::cout << std::endl;
    std::cout << "\033[1mTIPS:\033[0m" << std::endl;
    std::cout << "  • Run `z3ed proposal list` frequently to monitor progress" << std::endl;
    std::cout << "  • Use `--prompt` to describe tasks in natural language" << std::endl;
    std::cout << "  • Sandbox artifacts live alongside proposal logs" << std::endl;
    std::cout << std::endl;

  } else if (category == "widget") {
    std::cout << "\033[1m\033[36m🪟 GUI WIDGET DISCOVERY\033[0m" << std::endl;
    std::cout << std::endl;
    std::cout << "\033[1mCOMMANDS:\033[0m" << std::endl;
  std::cout << "  widget discover [--window=<name>] [--type=<widget>]" << std::endl;
  std::cout << "    Enumerate UI widgets available through automation hooks" << std::endl;
  std::cout << "    Options: --format=table|json, --limit <n>, --include-invisible, --include-disabled" << std::endl;
    std::cout << std::endl;
    std::cout << "\033[1mTIPS:\033[0m" << std::endl;
    std::cout << "  • Requires the YAZE GUI to be running locally" << std::endl;
    std::cout << "  • Combine with `z3ed proposal run` for automated UI tests" << std::endl;
    std::cout << std::endl;

  } else if (category == "patch") {
    std::cout << "\033[1m\033[36m🔧 ROM PATCHING COMMANDS\033[0m" << std::endl;
    std::cout << std::endl;
    std::cout << "\033[1mDESCRIPTION:\033[0m" << std::endl;
    std::cout << "  Apply patches and extract symbols from assembly files." << std::endl;
    std::cout << std::endl;
    std::cout << "\033[1mCOMMANDS:\033[0m" << std::endl;
    std::cout << std::endl;
    std::cout << "  \033[1mpatch apply-asar\033[0m <patch.asm>" << std::endl;
    std::cout << "    Apply Asar 65816 assembly patch to ROM" << std::endl;
    std::cout << "    Options: --rom=<file>, --output=<file>" << std::endl;
    std::cout << "    Example: z3ed patch apply-asar custom.asm --rom=zelda3.sfc" << std::endl;
    std::cout << std::endl;
    std::cout << "  \033[1mpatch apply-bps\033[0m <patch.bps>" << std::endl;
    std::cout << "    Apply BPS binary patch to ROM" << std::endl;
    std::cout << "    Options: --rom=<file>, --output=<file>" << std::endl;
    std::cout << "    Example: z3ed patch apply-bps hack.bps --rom=zelda3.sfc" << std::endl;
    std::cout << std::endl;
    std::cout << "  \033[1mpatch extract-symbols\033[0m <patch.asm>" << std::endl;
    std::cout << "    Extract symbol table from assembly file" << std::endl;
    std::cout << "    Example: z3ed patch extract-symbols code.asm" << std::endl;
    std::cout << std::endl;
    std::cout << "\033[1mRELATED:\033[0m" << std::endl;
    std::cout << "  z3ed help rom         ROM operations and validation" << std::endl;
    std::cout << std::endl;
    
  } else if (category == "rom") {
    std::cout << "\033[1m\033[36m📦 ROM OPERATIONS\033[0m" << std::endl;
    std::cout << std::endl;
    std::cout << "\033[1mCOMMANDS:\033[0m" << std::endl;
    std::cout << std::endl;
    std::cout << "  \033[1mrom info\033[0m" << std::endl;
    std::cout << "    Display ROM header and metadata" << std::endl;
    std::cout << "    Example: z3ed rom info --rom=zelda3.sfc" << std::endl;
    std::cout << std::endl;
    std::cout << "  \033[1mrom diff\033[0m" << std::endl;
    std::cout << "    Compare two ROM files byte-by-byte" << std::endl;
    std::cout << "    Example: z3ed rom diff --src=original.sfc --modified=hacked.sfc" << std::endl;
    std::cout << std::endl;
    std::cout << "  \033[1mrom generate-golden\033[0m" << std::endl;
    std::cout << "    Create golden test reference file" << std::endl;
    std::cout << "    Example: z3ed rom generate-golden --rom=zelda3.sfc" << std::endl;
    std::cout << std::endl;
    std::cout << "  \033[1mrom validate\033[0m" << std::endl;
    std::cout << "    Validate ROM checksum and structure" << std::endl;
    std::cout << "    Example: z3ed rom validate --rom=zelda3.sfc" << std::endl;
    std::cout << std::endl;
    
  } else if (category == "overworld") {
    std::cout << "\033[1m\033[36m🗺️  OVERWORLD COMMANDS\033[0m" << std::endl;
    std::cout << std::endl;
    std::cout << "\033[1mDESCRIPTION:\033[0m" << std::endl;
    std::cout << "  Inspect and modify overworld map data, tiles, and warps." << std::endl;
    std::cout << std::endl;
    std::cout << "\033[1mCOMMANDS:\033[0m" << std::endl;
    std::cout << std::endl;
    std::cout << "  \033[1moverworld get-tile\033[0m" << std::endl;
    std::cout << "    Get tile ID at specific coordinates" << std::endl;
    std::cout << "    Example: z3ed overworld get-tile --x=10 --y=20 --map=0 --rom=zelda3.sfc" << std::endl;
    std::cout << std::endl;
    std::cout << "  \033[1moverworld set-tile\033[0m" << std::endl;
    std::cout << "    Place tile at coordinates" << std::endl;
    std::cout << "    Example: z3ed overworld set-tile --x=10 --y=20 --tile=0x42 --rom=zelda3.sfc" << std::endl;
    std::cout << std::endl;
    std::cout << "  \033[1moverworld find-tile\033[0m" << std::endl;
    std::cout << "    Search for all occurrences of a tile" << std::endl;
    std::cout << "    Example: z3ed overworld find-tile --tile=0x42 --rom=zelda3.sfc" << std::endl;
    std::cout << std::endl;
    std::cout << "  \033[1moverworld describe-map\033[0m" << std::endl;
    std::cout << "    Show map metadata and properties" << std::endl;
    std::cout << "    Example: z3ed overworld describe-map --map=0 --rom=zelda3.sfc" << std::endl;
    std::cout << std::endl;
    std::cout << "  \033[1moverworld list-warps\033[0m" << std::endl;
    std::cout << "    List all entrances and exits" << std::endl;
    std::cout << "    Example: z3ed overworld list-warps --rom=zelda3.sfc" << std::endl;
    std::cout << std::endl;
    std::cout << "  \033[1moverworld select-rect\033[0m" << std::endl;
    std::cout << "    Select a rectangular region of tiles" << std::endl;
    std::cout << "    Example: z3ed overworld select-rect --map=0 --x1=5 --y1=5 --x2=10 --y2=10" << std::endl;
    std::cout << std::endl;
    std::cout << "  \033[1moverworld scroll-to\033[0m" << std::endl;
    std::cout << "    Scroll canvas to show specific tile" << std::endl;
    std::cout << "    Example: z3ed overworld scroll-to --map=0 --x=10 --y=10 --center" << std::endl;
    std::cout << std::endl;
    std::cout << "  \033[1moverworld set-zoom\033[0m" << std::endl;
    std::cout << "    Set canvas zoom level (0.25-4.0)" << std::endl;
    std::cout << "    Example: z3ed overworld set-zoom --zoom=1.5" << std::endl;
    std::cout << std::endl;
    std::cout << "  \033[1moverworld get-visible-region\033[0m" << std::endl;
    std::cout << "    Get currently visible tile region" << std::endl;
    std::cout << "    Example: z3ed overworld get-visible-region --map=0 --format=json" << std::endl;
    std::cout << std::endl;
    
  } else if (category == "dungeon") {
    std::cout << "\033[1m\033[36m🏰 DUNGEON COMMANDS\033[0m" << std::endl;
    std::cout << std::endl;
    std::cout << "\033[1mCOMMANDS:\033[0m" << std::endl;
    std::cout << std::endl;
    std::cout << "  \033[1mdungeon export\033[0m" << std::endl;
    std::cout << "    Export dungeon room data to JSON" << std::endl;
    std::cout << "    Example: z3ed dungeon export --room=5 --rom=zelda3.sfc" << std::endl;
    std::cout << std::endl;
    std::cout << "  \033[1mdungeon import\033[0m" << std::endl;
    std::cout << "    Import dungeon data from JSON" << std::endl;
    std::cout << "    Example: z3ed dungeon import --file=room5.json --rom=zelda3.sfc" << std::endl;
    std::cout << std::endl;
    
  } else if (category == "gfx" || category == "graphics") {
    std::cout << "\033[1m\033[36m🎨 GRAPHICS COMMANDS\033[0m" << std::endl;
    std::cout << std::endl;
    std::cout << "\033[1mCOMMANDS:\033[0m" << std::endl;
    std::cout << std::endl;
    std::cout << "  \033[1mgfx export-sheet\033[0m" << std::endl;
    std::cout << "    Export graphics sheet to PNG" << std::endl;
    std::cout << "    Example: z3ed gfx export-sheet --sheet=0 --rom=zelda3.sfc" << std::endl;
    std::cout << std::endl;
    std::cout << "  \033[1mgfx import-sheet\033[0m" << std::endl;
    std::cout << "    Import graphics from PNG" << std::endl;
    std::cout << "    Example: z3ed gfx import-sheet --file=custom.png --rom=zelda3.sfc" << std::endl;
    std::cout << std::endl;
    std::cout << "\033[1mRELATED:\033[0m" << std::endl;
    std::cout << "  z3ed help palette     Palette manipulation commands" << std::endl;
    std::cout << std::endl;
    
  } else if (category == "palette") {
    std::cout << "\033[1m\033[36m🎨 PALETTE COMMANDS\033[0m" << std::endl;
    std::cout << std::endl;
    std::cout << "\033[1mCOMMANDS:\033[0m" << std::endl;
    std::cout << std::endl;
    std::cout << "  \033[1mpalette export\033[0m" << std::endl;
    std::cout << "    Export palette data" << std::endl;
    std::cout << "    Example: z3ed palette export --palette=0 --rom=zelda3.sfc" << std::endl;
    std::cout << std::endl;
    std::cout << "  \033[1mpalette import\033[0m" << std::endl;
    std::cout << "    Import palette data" << std::endl;
    std::cout << "    Example: z3ed palette import --file=colors.pal --rom=zelda3.sfc" << std::endl;
    std::cout << std::endl;
    
  } else {
    std::cout << "\033[1m\033[31mUnknown category: " << category << "\033[0m" << std::endl;
    std::cout << std::endl;
  std::cout << "Available categories: agent, chat, proposal, widget, patch, rom, overworld, dungeon, gfx, palette" << std::endl;
    std::cout << std::endl;
    std::cout << "Use 'z3ed --help' to see all commands." << std::endl;
  }
}

void ModernCLI::ShowCommandSummary() const {
  std::cout << GetColoredLogo() << std::endl;
  std::cout << std::endl;
  std::cout << "\033[1m\033[36mCOMMANDS OVERVIEW\033[0m" << std::endl;
  std::cout << std::endl;

  for (const auto& [key, info] : commands_) {
    std::string headline = info.description;
    const size_t newline_pos = headline.find('\n');
    if (newline_pos != std::string::npos) {
      headline = headline.substr(0, newline_pos);
    }
    if (headline.empty()) {
      headline = info.usage;
    }
    if (headline.size() > 80) {
      headline = absl::StrCat(headline.substr(0, 77), "…");
    }

    std::string label = info.name;
    if (label.size() > 24) {
      label = absl::StrCat(label.substr(0, 23), "…");
    }

  std::cout << "  "
        << absl::StrFormat("%-24s%s", label, headline) << std::endl;
  }

  std::cout << std::endl;
  std::cout << "Use \033[90mz3ed help <topic>\033[0m for detailed information." << std::endl;
}

absl::Status ModernCLI::Run(int argc, char* argv[]) {
  if (argc < 2) {
    ShowHelp();
    return absl::OkStatus();
  }

  std::vector<std::string> args;
  args.reserve(argc - 1);
  for (int i = 1; i < argc; ++i) {
    args.emplace_back(argv[i]);
  }

  // Handle "help <category>" command
  if (args.size() >= 1 && args[0] == "help") {
    if (args.size() == 1) {
      ShowHelp();
      return absl::OkStatus();
    }
    ShowCategoryHelp(args[1]);
    return absl::OkStatus();
  }

  const CommandInfo* command_info = nullptr;
  size_t consumed_tokens = 0;

  if (args.size() >= 2) {
    std::string candidate = absl::StrCat(args[0], " ", args[1]);
    auto it = commands_.find(candidate);
    if (it != commands_.end()) {
      command_info = &it->second;
      consumed_tokens = 2;
    }
  }

  if (command_info == nullptr && !args.empty()) {
    auto it = commands_.find(args[0]);
    if (it != commands_.end()) {
      command_info = &it->second;
      consumed_tokens = 1;
    }
  }

  if (command_info == nullptr) {
    ShowHelp();
    std::string joined = args.empty() ? std::string() : absl::StrJoin(args, " ");
    return absl::NotFoundError(
        absl::StrCat("Unknown command: ", joined.empty() ? "<none>" : joined));
  }

  std::vector<std::string> command_args(args.begin() + consumed_tokens, args.end());
  return command_info->handler(command_args);
}

CommandHandler* ModernCLI::GetCommandHandler(const std::string& name) {
    // This is not ideal, but it will work for now.
    if (name == "patch apply-asar") {
        static AsarPatch handler;
        return &handler;
    }
    if (name == "palette") {
        static Palette handler;
        return &handler;
    }
    if (name == "command-palette") {
        static CommandPalette handler;
        return &handler;
    }
    return nullptr;
}

absl::Status ModernCLI::HandleAsarPatchCommand(const std::vector<std::string>& args) {
    AsarPatch handler;
    return handler.Run(args);
}

absl::Status ModernCLI::HandleBpsPatchCommand(const std::vector<std::string>& args) {
    ApplyPatch handler;
    return handler.Run(args);
}

absl::Status ModernCLI::HandleRomInfoCommand(const std::vector<std::string>& args) {
    RomInfo handler;
    return handler.Run(args);
}

absl::Status ModernCLI::HandleExtractSymbolsCommand(const std::vector<std::string>& args) {
    // Use the AsarWrapper to extract symbols
    yaze::core::AsarWrapper wrapper;
    RETURN_IF_ERROR(wrapper.Initialize());
    
    auto symbols_result = wrapper.ExtractSymbols(args[0]);
    if (!symbols_result.ok()) {
      return symbols_result.status();
    }

    const auto& symbols = symbols_result.value();
    std::cout << "🏷️  Extracted " << symbols.size() << " symbols from " << args[0] << ":" << std::endl;
    std::cout << std::endl;
    
    for (const auto& symbol : symbols) {
      std::cout << absl::StrFormat("  %-20s @ $%06X", symbol.name, symbol.address) << std::endl;
    }
    
    return absl::OkStatus();
}

absl::Status ModernCLI::HandleAgentCommand(const std::vector<std::string>& args) {
    Agent handler;
    return handler.Run(args);
}

absl::Status ModernCLI::HandleCollabCommand(const std::vector<std::string>& args) {
  if (args.empty()) {
    return absl::InvalidArgumentError(
        "Usage: z3ed collab <start|status> [options]\n"
        "  start  - Start the collaboration server\n"
        "  status - Check server status");
  }

  const std::string& subcommand = args[0];

  if (subcommand == "start") {
    std::string port = "8765";
    
    // Parse port argument
    for (size_t i = 1; i < args.size(); ++i) {
      if (absl::StartsWith(args[i], "--port=")) {
        port = args[i].substr(7);
      } else if (args[i] == "--port" && i + 1 < args.size()) {
        port = args[++i];
      }
    }

    // Determine server directory
    std::string server_dir;
    if (const char* yaze_root = std::getenv("YAZE_ROOT")) {
      server_dir = std::string(yaze_root);
    } else {
      // Assume we're in build directory, server is ../yaze-server
      server_dir = "..";
    }
    
    std::cout << "🚀 Starting collaboration server on port " << port << "...\n";
    std::cout << "   Server will be accessible at ws://localhost:" << port << "\n\n";
    
    // Build platform-specific command
    std::string command;
#ifdef _WIN32
    // Windows: Use cmd.exe to run npm start
    command = "cd /D \"" + server_dir + "\\..\\yaze-server\" && set PORT=" + 
              port + " && npm start";
#else
    // Unix: Use bash script
    command = "cd \"" + server_dir + "/../yaze-server\" && PORT=" + 
              port + " node server.js &";
#endif
    
    int result = std::system(command.c_str());
    
    if (result != 0) {
      std::cout << "⚠️  Note: Server may not be installed. To install:\n";
      std::cout << "   cd yaze-server && npm install\n";
      return absl::InternalError("Failed to start collaboration server");
    }
    
    std::cout << "✓ Server started (may take a few seconds to initialize)\n";
    return absl::OkStatus();
  }
  
  if (subcommand == "status") {
    // Check if Node.js process is running (platform-specific)
    int result;
#ifdef _WIN32
    // Windows: Use tasklist to find node.exe
    result = std::system("tasklist /FI \"IMAGENAME eq node.exe\" 2>NUL | find /I \"node.exe\" >NUL");
#else
    // Unix: Use pgrep
    result = std::system("pgrep -f 'node.*server.js' > /dev/null 2>&1");
#endif
    
    if (result == 0) {
      std::cout << "✓ Collaboration server appears to be running\n";
      std::cout << "  Connect from YAZE: Debug → Agent Chat → Network mode\n";
    } else {
      std::cout << "○ Collaboration server is not running\n";
      std::cout << "  Start with: z3ed collab start\n";
    }
    
    return absl::OkStatus();
  }

  return absl::InvalidArgumentError(absl::StrFormat("Unknown subcommand: %s", subcommand));
}

absl::Status ModernCLI::HandleProjectBuildCommand(const std::vector<std::string>& args) {
    ProjectBuild handler;
    return handler.Run(args);
}

absl::Status ModernCLI::HandleProjectInitCommand(const std::vector<std::string>& args) {
    ProjectInit handler;
    return handler.Run(args);
}

absl::Status ModernCLI::HandleRomGenerateGoldenCommand(const std::vector<std::string>& args) {
    std::string rom_file = absl::GetFlag(FLAGS_rom);
    if (!args.empty()) {
      rom_file = args[0];
    }
    
    if (rom_file.empty()) {
      return absl::InvalidArgumentError("ROM file required (use --rom=<file> or provide as argument)");
    }

    Open handler;
    return handler.Run({rom_file});
}

absl::Status ModernCLI::HandleDungeonExportCommand(const std::vector<std::string>& args) {
    DungeonExport handler;
    return handler.Run(args);
}

absl::Status ModernCLI::HandleDungeonListObjectsCommand(const std::vector<std::string>& args) {
    DungeonListObjects handler;
    return handler.Run(args);
}

absl::Status ModernCLI::HandleGfxExportCommand(const std::vector<std::string>& args) {
    GfxExport handler;
    return handler.Run(args);
}

absl::Status ModernCLI::HandleGfxImportCommand(const std::vector<std::string>& args) {
    GfxImport handler;
    return handler.Run(args);
}

absl::Status ModernCLI::HandleCommandPaletteCommand(const std::vector<std::string>& args) {
    CommandPalette handler;
    return handler.Run(args);
}

absl::Status ModernCLI::HandlePaletteExportCommand(const std::vector<std::string>& args) {
    PaletteExport handler;
    return handler.Run(args);
}

absl::Status ModernCLI::HandlePaletteCommand(const std::vector<std::string>& args) {
    Palette handler;
    return handler.Run(args);
}

absl::Status ModernCLI::HandlePaletteImportCommand(const std::vector<std::string>& args) {
    PaletteImport handler;
    return handler.Run(args);
}

absl::Status ModernCLI::HandleRomDiffCommand(const std::vector<std::string>& args) {
    RomDiff handler;
    return handler.Run(args);
}

absl::Status ModernCLI::HandleRomValidateCommand(const std::vector<std::string>& args) {
    RomValidate handler;
    return handler.Run(args);
}

absl::Status ModernCLI::HandleOverworldGetTileCommand(const std::vector<std::string>& args) {
    OverworldGetTile handler;
    return handler.Run(args);
}

absl::Status ModernCLI::HandleOverworldFindTileCommand(const std::vector<std::string>& args) {
  OverworldFindTile handler;
  return handler.Run(args);
}

absl::Status ModernCLI::HandleOverworldDescribeMapCommand(const std::vector<std::string>& args) {
  OverworldDescribeMap handler;
  return handler.Run(args);
}

absl::Status ModernCLI::HandleOverworldListWarpsCommand(const std::vector<std::string>& args) {
  OverworldListWarps handler;
  return handler.Run(args);
}

absl::Status ModernCLI::HandleOverworldSetTileCommand(const std::vector<std::string>& args) {
    OverworldSetTile handler;
    return handler.Run(args);
}

absl::Status ModernCLI::HandleOverworldSelectRectCommand(const std::vector<std::string>& args) {
    OverworldSelectRect handler;
    return handler.Run(args);
}

absl::Status ModernCLI::HandleOverworldScrollToCommand(const std::vector<std::string>& args) {
    OverworldScrollTo handler;
    return handler.Run(args);
}

absl::Status ModernCLI::HandleOverworldSetZoomCommand(const std::vector<std::string>& args) {
    OverworldSetZoom handler;
    return handler.Run(args);
}

absl::Status ModernCLI::HandleOverworldGetVisibleRegionCommand(const std::vector<std::string>& args) {
    OverworldGetVisibleRegion handler;
    return handler.Run(args);
}

absl::Status ModernCLI::HandleSpriteCreateCommand(const std::vector<std::string>& args) {
  SpriteCreate handler;
  return handler.Run(args);
}

absl::Status ModernCLI::HandleChatEntryCommand(
  const std::vector<std::string>& args) {
  std::string mode = "simple";
  std::optional<std::string> prompt;
  std::vector<std::string> forwarded;

  for (size_t i = 0; i < args.size(); ++i) {
    const std::string& token = args[i];
    if (absl::StartsWith(token, "--mode=")) {
      mode = absl::AsciiStrToLower(token.substr(7));
      continue;
    }
    if (token == "--mode" && i + 1 < args.size()) {
      mode = absl::AsciiStrToLower(args[i + 1]);
      ++i;
      continue;
    }
    if (absl::StartsWith(token, "--prompt=")) {
      prompt = token.substr(9);
      continue;
    }
    if (token == "--prompt" && i + 1 < args.size()) {
      prompt = args[i + 1];
      ++i;
      continue;
    }
    if (token == "--quiet" || token == "-q") {
      absl::SetFlag(&FLAGS_quiet, true);
      continue;
    }
    if (!absl::StartsWith(token, "--") && !prompt.has_value()) {
      prompt = token;
      continue;
    }
    forwarded.push_back(token);
  }

  const std::string normalized_mode = absl::AsciiStrToLower(mode);

  auto has_batch_file = [&forwarded]() {
    for (const auto& token : forwarded) {
      if (absl::StartsWith(token, "--file") || token == "--file") {
        return true;
      }
    }
    return false;
  };

  std::vector<std::string> agent_args;
  if (normalized_mode == "gui" || normalized_mode == "visual" ||
    normalized_mode == "tui") {
    if (prompt.has_value()) {
      return absl::InvalidArgumentError(
        "GUI chat mode launches the interactive TUI and does not accept a --prompt value.");
    }
    agent_args.push_back("chat");
  } else if (normalized_mode == "test" || normalized_mode == "qa") {
    if (prompt.has_value()) {
      return absl::InvalidArgumentError(
        "Test conversation mode does not accept an inline prompt.");
    }
    agent_args.push_back("test-conversation");
  } else {
    if (normalized_mode == "batch" && !has_batch_file()) {
      return absl::InvalidArgumentError(
        "Batch chat mode requires a --file=<path> option.");
    }
    agent_args.push_back("simple-chat");
    if (prompt.has_value()) {
      agent_args.push_back(*prompt);
    }
  }

  agent_args.insert(agent_args.end(), forwarded.begin(), forwarded.end());
  return HandleAgentCommand(agent_args);
}

absl::Status ModernCLI::HandleProposalCommand(
  const std::vector<std::string>& args) {
  if (args.empty()) {
    ShowCategoryHelp("proposal");
    return absl::OkStatus();
  }

  std::string subcommand = absl::AsciiStrToLower(args[0]);
  std::vector<std::string> forwarded(args.begin() + 1, args.end());
  std::vector<std::string> agent_args;

  if (subcommand == "run" || subcommand == "plan") {
    agent_args.push_back(subcommand);
  } else if (subcommand == "list") {
    agent_args.push_back("list");
  } else if (subcommand == "diff" || subcommand == "show") {
    agent_args.push_back("diff");
  } else if (subcommand == "accept") {
    agent_args.push_back("accept");
  } else if (subcommand == "commit") {
    agent_args.push_back("commit");
  } else if (subcommand == "revert" || subcommand == "reject") {
    agent_args.push_back("revert");
  } else if (subcommand == "test") {
    agent_args.push_back("test");
  } else {
    return absl::InvalidArgumentError(
      absl::StrCat("Unknown proposal command: ", subcommand,
              ". Valid actions: run, plan, list, diff, show, accept, commit, revert."));
  }

  agent_args.insert(agent_args.end(), forwarded.begin(), forwarded.end());
  return HandleAgentCommand(agent_args);
}

absl::Status ModernCLI::HandleWidgetCommand(
  const std::vector<std::string>& args) {
  if (args.empty()) {
    ShowCategoryHelp("widget");
    return absl::OkStatus();
  }

  std::vector<std::string> forwarded(args.begin(), args.end());
  std::string subcommand = absl::AsciiStrToLower(forwarded[0]);
  std::vector<std::string> agent_args;

  if (subcommand == "discover") {
    agent_args.push_back("gui");
    agent_args.insert(agent_args.end(), forwarded.begin(), forwarded.end());
  } else {
    return absl::InvalidArgumentError(
      absl::StrCat("Unknown widget command: ", forwarded[0],
              ". Try 'z3ed widget discover'."));
  }

  return HandleAgentCommand(agent_args);
}

}  // namespace cli
}  // namespace yaze
