from utils.display import Display


# ESP32 Commands organized by module (matches Kconfig modules)
ESP_MODULES = {
    "system": {
        "description": "Core system commands",
        "commands": {
            "system_reboot": "Reboot the ESP32 device",
            "system_mem": "Get memory info (heap, internal)",
            "system_uptime": "Get device uptime",
        }
    },
    "network": {
        "description": "Network tools",
        "commands": {
            "ping": "Ping a host (ping <host>)",
            "arp_scan": "ARP scan the local network",
            "proxy_start": "Start TCP proxy (proxy_start <ip> <port>)",
            "proxy_stop": "Stop TCP proxy",
            "dos_tcp": "TCP flood (dos_tcp <ip> <port> <count>)",
        }
    },
    "fakeap": {
        "description": "Fake Access Point module",
        "commands": {
            "fakeap_start": "Start fake AP (fakeap_start <ssid> [open|wpa2] [pass])",
            "fakeap_stop": "Stop fake AP",
            "fakeap_status": "Show fake AP status",
            "fakeap_clients": "List connected clients",
            "fakeap_portal_start": "Start captive portal",
            "fakeap_portal_stop": "Stop captive portal",
            "fakeap_sniffer_on": "Enable packet sniffer",
            "fakeap_sniffer_off": "Disable packet sniffer",
        }
    },
    "recon": {
        "description": "Reconnaissance module (Camera + MLAT)",
        "commands": {
            "cam_start": "Start camera streaming (cam_start <ip> <port>)",
            "cam_stop": "Stop camera streaming",
            "mlat config": "Set position (mlat config [gps|local] <c1> <c2>)",
            "mlat mode": "Set scan mode (mlat mode <ble|wifi>)",
            "mlat start": "Start MLAT scanning (mlat start <mac>)",
            "mlat stop": "Stop MLAT scanning",
            "mlat status": "Show MLAT status",
        }
    }
}


class HelpManager:
    def __init__(self, command_registry, dev_mode: bool = False):
        self.commands = command_registry
        self.dev_mode = dev_mode

    def show(self, args: list[str]):
        if args:
            self._show_command_help(args[0])
        else:
            self._show_global_help()

    def show_modules(self):
        """Show ESP commands organized by module."""
        Display.system_message("=== ESP32 COMMANDS BY MODULE ===\n")

        for module_name, module_info in ESP_MODULES.items():
            print(f"\033[1;35m[{module_name.upper()}]\033[0m - {module_info['description']}")
            for cmd_name, cmd_desc in module_info["commands"].items():
                print(f"  \033[36m{cmd_name:<12}\033[0m {cmd_desc}")
            print()

        print("\033[90mUse 'help <command>' for detailed help on a specific command.\033[0m")
        print("\033[90mSend commands with: send <device_id|all> <command> [args...]\033[0m")

    def _show_global_help(self):
        Display.system_message("=== ESPILON C2 HELP ===")
        print("\n\033[1mC2 Commands:\033[0m")
        print("  \033[36mhelp\033[0m [command]      Show help or help for a specific command")
        print("  \033[36mlist\033[0m                List connected ESP devices")
        print("  \033[36mmodules\033[0m             List ESP commands organized by module")
        print("  \033[36msend\033[0m <target> <cmd> Send a command to ESP device(s)")
        print("  \033[36mgroup\033[0m <action>      Manage device groups (add, remove, list, show)")
        print("  \033[36mactive_commands\033[0m     List currently running commands")
        print("  \033[36mclear\033[0m               Clear terminal screen")
        print("  \033[36mexit\033[0m                Exit C2")

        print("\n\033[1mServer Commands:\033[0m")
        print("  \033[36mweb\033[0m start|stop|status     Web dashboard server")
        print("  \033[36mcamera\033[0m start|stop|status  Camera UDP receiver")

        print("\n\033[1mESP Commands:\033[0m (use 'modules' for detailed list)")
        registered_cmds = self.commands.list()
        if registered_cmds:
            for name in registered_cmds:
                handler = self.commands.get(name)
                print(f"  \033[36m{name:<15}\033[0m {handler.description}")
        else:
            print("  \033[90m(no registered commands - use 'send' with any ESP command)\033[0m")

        if self.dev_mode:
            print("\n\033[33mDEV MODE:\033[0m Send arbitrary text: send <target> <any text>")

    def _show_command_help(self, command_name: str):
        # CLI Commands
        if command_name == "list":
            Display.system_message("Help for 'list' command:")
            print("  Usage: list")
            print("  Description: Displays all connected ESP devices with ID, IP, status,")
            print("               connection duration, and last seen timestamp.")

        elif command_name == "send":
            Display.system_message("Help for 'send' command:")
            print("  Usage: send <device_id|all|group <name>> <command> [args...]")
            print("  Description: Sends a command to one or more ESP devices.")
            print("  Examples:")
            print("    send ESP_ABC123 reboot")
            print("    send all wifi status")
            print("    send group scanners mlat start AA:BB:CC:DD:EE:FF")

        elif command_name == "group":
            Display.system_message("Help for 'group' command:")
            print("  Usage: group <action> [args...]")
            print("  Actions:")
            print("    add <name> <id1> [id2...]    Add devices to a group")
            print("    remove <name> <id1> [id2...] Remove devices from a group")
            print("    list                          List all groups")
            print("    show <name>                   Show group members")

        elif command_name == "web":
            Display.system_message("Help for 'web' command:")
            print("  Usage: web <start|stop|status>")
            print("  Description: Control the web dashboard server.")
            print("  Actions:")
            print("    start   Start the web server (dashboard, cameras, MLAT)")
            print("    stop    Stop the web server")
            print("    status  Show server status and MLAT engine info")
            print("  Default URL: http://127.0.0.1:5000")

        elif command_name == "camera":
            Display.system_message("Help for 'camera' command:")
            print("  Usage: camera <start|stop|status>")
            print("  Description: Control the camera UDP receiver.")
            print("  Actions:")
            print("    start   Start UDP receiver for camera frames")
            print("    stop    Stop UDP receiver")
            print("    status  Show receiver stats (packets, frames, errors)")
            print("  Default port: 12345")

        elif command_name == "modules":
            Display.system_message("Help for 'modules' command:")
            print("  Usage: modules")
            print("  Description: List all ESP32 commands organized by module.")
            print("  Modules: system, network, fakeap, recon")

        elif command_name in ["clear", "exit", "active_commands"]:
            Display.system_message(f"Help for '{command_name}' command:")
            print(f"  Usage: {command_name}")
            descs = {
                "clear": "Clear the terminal screen",
                "exit": "Exit the C2 application",
                "active_commands": "Show all commands currently being executed"
            }
            print(f"  Description: {descs.get(command_name, '')}")

        # ESP Commands (by module or registered)
        else:
            # Check in modules first
            for module_name, module_info in ESP_MODULES.items():
                if command_name in module_info["commands"]:
                    Display.system_message(f"ESP Command '{command_name}' [{module_name.upper()}]:")
                    print(f"  Description: {module_info['commands'][command_name]}")
                    self._show_esp_command_detail(command_name)
                    return

            # Check registered commands
            handler = self.commands.get(command_name)
            if handler:
                Display.system_message(f"ESP Command '{command_name}':")
                print(f"  Description: {handler.description}")
                if hasattr(handler, 'usage'):
                    print(f"  Usage: {handler.usage}")
            else:
                Display.error(f"No help available for '{command_name}'.")

    def _show_esp_command_detail(self, cmd: str):
        """Show detailed help for specific ESP commands."""
        details = {
            # MLAT subcommands
            "mlat config": """
  Usage: send <device> mlat config [gps|local] <coord1> <coord2>
  GPS mode:   mlat config gps <lat> <lon>    - degrees
  Local mode: mlat config local <x> <y>      - meters
  Examples:
    send ESP1 mlat config gps 48.8566 2.3522
    send ESP1 mlat config local 10.0 5.5
    send ESP1 mlat config 48.8566 2.3522  (backward compat: GPS)""",

            "mlat mode": """
  Usage: send <device> mlat mode <ble|wifi>
  Example: send ESP1 mlat mode ble""",

            "mlat start": """
  Usage: send <device> mlat start <mac>
  Example: send ESP1 mlat start AA:BB:CC:DD:EE:FF""",

            "mlat stop": """
  Usage: send <device> mlat stop""",

            "mlat status": """
  Usage: send <device> mlat status""",

            # Camera commands
            "cam_start": """
  Usage: send <device> cam_start <ip> <port>
  Description: Start camera streaming to C2 UDP receiver
  Example: send ESP_CAM cam_start 192.168.1.100 12345""",

            "cam_stop": """
  Usage: send <device> cam_stop
  Description: Stop camera streaming""",

            # FakeAP commands
            "fakeap_start": """
  Usage: send <device> fakeap_start <ssid> [open|wpa2] [password]
  Examples:
    send ESP1 fakeap_start FreeWiFi
    send ESP1 fakeap_start SecureNet wpa2 mypassword""",

            "fakeap_stop": """
  Usage: send <device> fakeap_stop""",

            "fakeap_status": """
  Usage: send <device> fakeap_status
  Shows: AP running, portal status, sniffer status, client count""",

            "fakeap_clients": """
  Usage: send <device> fakeap_clients
  Lists all connected clients to the fake AP""",

            "fakeap_portal_start": """
  Usage: send <device> fakeap_portal_start
  Description: Enable captive portal (requires fakeap running)""",

            "fakeap_portal_stop": """
  Usage: send <device> fakeap_portal_stop""",

            "fakeap_sniffer_on": """
  Usage: send <device> fakeap_sniffer_on
  Description: Enable packet sniffing""",

            "fakeap_sniffer_off": """
  Usage: send <device> fakeap_sniffer_off""",

            # Network commands
            "ping": """
  Usage: send <device> ping <host>
  Example: send ESP1 ping 8.8.8.8""",

            "arp_scan": """
  Usage: send <device> arp_scan
  Description: Scan local network for hosts""",

            "proxy_start": """
  Usage: send <device> proxy_start <ip> <port>
  Example: send ESP1 proxy_start 192.168.1.100 8080""",

            "proxy_stop": """
  Usage: send <device> proxy_stop""",

            "dos_tcp": """
  Usage: send <device> dos_tcp <ip> <port> <count>
  Example: send ESP1 dos_tcp 192.168.1.100 80 1000""",

            # System commands
            "system_reboot": """
  Usage: send <device> system_reboot
  Description: Reboot the ESP32 device""",

            "system_mem": """
  Usage: send <device> system_mem
  Shows: heap_free, heap_min, internal_free""",

            "system_uptime": """
  Usage: send <device> system_uptime
  Shows: uptime in days/hours/minutes/seconds"""
        }

        if cmd in details:
            print(details[cmd])
