#!/usr/bin/env python3
"""uxsend.py - send yourself a UserAlertX alert (any OS with Python 3).

  python3 uxsend.py                       # asks "Enter text body"
  python3 uxsend.py "Backup finished"     # one-shot
  python3 uxsend.py -m sms "Server back"  # force text (-m email = email)

Uses only Python's standard library - nothing to install.

API key: USERALERTX_API_KEY env var, else ~/.useralertx_key, else it asks
(and can save it there). Your key is on your account page
(useralertx.com -> Account).

To use it from your own code:  from uxsend import send_alert
                                send_alert(api_key, "Disk almost full")
"""
import json
import os
import sys
import urllib.error
import urllib.parse
import urllib.request

URL = os.environ.get("USERALERTX_URL", "https://useralertx.com/cgi-bin/itmessages.cgi")
KEYFILE = os.path.join(os.path.expanduser("~"), ".useralertx_key")


def ask(prompt):
    """input() that treats end-of-input (Ctrl+D / Ctrl+Z, piped input) as blank."""
    try:
        return input(prompt)
    except (EOFError, KeyboardInterrupt):
        print()
        return ""


def send_alert(api_key, body, title=None, method=None):
    """Send one alert. Returns (http_status, reply_dict)."""
    form = {"body": body}
    if title:
        form["title"] = title
    if method:
        form["method"] = method
    req = urllib.request.Request(
        URL,
        data=urllib.parse.urlencode(form).encode(),
        # Python's default User-Agent ("Python-urllib/...") is blocked by
        # our Cloudflare front end - always send your own name.
        headers={"X-Api-Key": api_key, "User-Agent": "UserAlertX-example-py/1.0"},
        method="POST",
    )
    try:
        with urllib.request.urlopen(req, timeout=20) as r:
            return r.status, json.loads(r.read().decode())
    except urllib.error.HTTPError as e:  # 4xx replies still explain why
        try:
            return e.code, json.loads(e.read().decode())
        except ValueError:
            return e.code, {"error": "unexpected reply"}


def get_key():
    key = os.environ.get("USERALERTX_API_KEY", "").strip()
    if not key and os.path.exists(KEYFILE):
        key = open(KEYFILE).read().strip()
    if not key:
        print("Your API key is on your UserAlertX account page (useralertx.com -> Account).")
        key = ask("Paste your API key: ").strip()
        if not key:
            sys.exit("No API key entered - stopping.")
        if ask(f"Save it in {KEYFILE}? (y/N) ").lower().startswith("y"):
            fd = os.open(KEYFILE, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o600)
            with os.fdopen(fd, "w") as f:
                f.write(key)
            print("Saved.")
    return key


def report(status, reply):
    if status == 200:
        print(f"Sent by {reply.get('method')} to {reply.get('target')} (message #{reply.get('message_id')}).")
    elif status == 202:
        print(f"Held: {reply.get('detail')}")
    else:
        print(f"Not sent (HTTP {status}): {reply.get('error') or reply.get('detail') or reply}")


def main():
    args = sys.argv[1:]
    method = None
    if len(args) >= 2 and args[0] == "-m":
        method, args = args[1], args[2:]
    key = get_key()
    if args:
        report(*send_alert(key, " ".join(args), method=method))
        return
    print("UserAlertX - send yourself an alert (Enter on an empty message to quit).")
    while True:
        body = ask("Enter text body: ").strip()
        if not body:
            break
        report(*send_alert(key, body, method=method))


if __name__ == "__main__":
    main()
