"""Append raw string query parameters to a trusted HTTP URL. Python 3.10+."""
import argparse
import sys
from urllib.parse import parse_qsl, urlencode, urlsplit, urlunsplit


def parameter(text):
    key, found, value = text.partition("=")
    if not found or not key:
        raise argparse.ArgumentTypeError("use a nonempty KEY=VALUE; VALUE may be empty")
    return key, value


def build_url(base, additions):
    if not base.isascii() or any(ord(c) <= 32 or ord(c) == 127 for c in base):
        raise ValueError("base must be an ASCII URL without whitespace or controls")
    parts = urlsplit(base)
    if parts.scheme not in {"http", "https"} or not parts.hostname:
        raise ValueError("base must have an http(s) scheme and a host")
    # Accessing port also rejects malformed or out-of-range port numbers.
    _ = parts.port
    pairs = parse_qsl(
        parts.query, keep_blank_values=True, encoding="utf-8",
        errors="strict", max_num_fields=1000, separator="&",
    )
    pairs.extend(additions)
    if len(pairs) > 1000:
        raise ValueError("at most 1000 query parameters are allowed")
    query = urlencode(pairs, encoding="utf-8", errors="strict")
    return urlunsplit(parts._replace(query=query))


def main():
    parser = argparse.ArgumentParser(description=__doc__, allow_abbrev=False)
    parser.add_argument("base", help="trusted, already encoded base URL")
    parser.add_argument(
        "--param", action="append", type=parameter, default=[],
        metavar="KEY=VALUE", help="raw string parameter; repeat to append more",
    )
    args = parser.parse_args()
    try:
        result = build_url(args.base, args.param)
    except ValueError as exc:
        print(f"ERROR: {exc}", file=sys.stderr)
        return 1
    print(result)
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
