#!/usr/bin/env python3
"""Send management commands to ESP32 CSI devices over UDP."""

import socket
import sys

from esp_ctl.auth import sign_command

DEFAULT_PORT = 5501
TIMEOUT = 2.0

USAGE = """\
Usage: esp-cmd <host> <command> [args...]

Host can be an IP address or mDNS hostname (e.g., amber-maple.local).

Commands:
  STATUS              Query device state (uptime, heap, RSSI, tx_power, rate)
  REBOOT              Restart the ESP32
  IDENTIFY            Blink LED solid for 5 seconds
  RATE <10-100>       Set ping frequency in Hz (saved to NVS)
  POWER <2-20>        Set TX power in dBm (saved to NVS)

Examples:
  esp-cmd amber-maple.local STATUS
  esp-cmd 192.168.129.30 RATE 50
  esp-cmd amber-maple.local IDENTIFY"""


def resolve(host):
    """Resolve hostname to IP address (supports mDNS .local)."""
    try:
        result = socket.getaddrinfo(host, DEFAULT_PORT, socket.AF_INET, socket.SOCK_DGRAM)
        return result[0][4][0]
    except socket.gaierror as e:
        print(f"ERR: cannot resolve {host}: {e}", file=sys.stderr)
        sys.exit(1)


def main():
    if len(sys.argv) < 3 or sys.argv[1] in ("-h", "--help"):
        print(USAGE)
        sys.exit(0 if sys.argv[1:] and sys.argv[1] in ("-h", "--help") else 2)

    host = sys.argv[1]
    cmd = sign_command(" ".join(sys.argv[2:]).strip())
    ip = resolve(host)

    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.settimeout(TIMEOUT)

    try:
        sock.sendto(cmd.encode(), (ip, DEFAULT_PORT))
        data, _ = sock.recvfrom(512)
        print(data.decode().strip())
    except socket.timeout:
        print(f"ERR: no reply from {host} ({ip}:{DEFAULT_PORT}), timeout {TIMEOUT}s", file=sys.stderr)
        sys.exit(1)
    except OSError as e:
        print(f"ERR: {e}", file=sys.stderr)
        sys.exit(1)
    finally:
        sock.close()


if __name__ == "__main__":
    main()
