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 _out(self, text: str):
        """Output helper that works in both CLI and TUI mode."""
        Display.system_message(text)

    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."""
        self._out("=== ESP32 COMMANDS BY MODULE ===")
        self._out("")

        for module_name, module_info in ESP_MODULES.items():
            self._out(f"[{module_name.upper()}] - {module_info['description']}")
            for cmd_name, cmd_desc in module_info["commands"].items():
                self._out(f"  {cmd_name:<20} {cmd_desc}")
            self._out("")

        self._out("Use 'help <command>' for detailed help on a specific command.")
        self._out("Send commands with: send <device_id|all> <command> [args...]")

    def _show_global_help(self):
        self._out("=== ESPILON C2 HELP ===")
        self._out("")
        self._out("C2 Commands:")
        self._out("  help [command]        Show help or help for a specific command")
        self._out("  list                  List connected ESP devices")
        self._out("  modules               List ESP commands organized by module")
        self._out("  send <target> <cmd>   Send a command to ESP device(s)")
        self._out("  group <action>        Manage device groups (add, remove, list, show)")
        self._out("  active_commands       List currently running commands")
        self._out("  clear                 Clear terminal screen")
        self._out("  exit                  Exit C2")
        self._out("")
        self._out("Server Commands:")
        self._out("  web start|stop|status     Web dashboard server")
        self._out("  camera start|stop|status  Camera UDP receiver")
        self._out("")
        self._out("ESP Commands: (use 'modules' for detailed list)")

        registered_cmds = self.commands.list()
        if registered_cmds:
            for name in registered_cmds:
                handler = self.commands.get(name)
                self._out(f"  {name:<15} {handler.description}")
        else:
            self._out("  (no registered commands - use 'send' with any ESP command)")

        if self.dev_mode:
            self._out("")
            self._out("DEV MODE: Send arbitrary text: send <target> <any text>")

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

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

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

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

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

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

        elif command_name in ["clear", "exit", "active_commands"]:
            self._out(f"Help for '{command_name}' command:")
            self._out(f"  Usage: {command_name}")
            descs = {
                "clear": "Clear the terminal screen",
                "exit": "Exit the C2 application",
                "active_commands": "Show all commands currently being executed"
            }
            self._out(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"]:
                    self._out(f"ESP Command '{command_name}' [{module_name.upper()}]:")
                    self._out(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:
                self._out(f"ESP Command '{command_name}':")
                self._out(f"  Description: {handler.description}")
                if hasattr(handler, 'usage'):
                    self._out(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",
            ],
            "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",
            ],
            "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_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",
            ],
            "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_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:
            for line in details[cmd]:
                self._out(line)
