#!/usr/bin/env bash
set -euo pipefail

default_socket="/run/uce/cli.sock"
if [[ -z "${UCE_CLI_SOCKET:-}" && -r /etc/uce/settings.cfg ]]; then
	configured_socket=$(awk -F= '/^[[:space:]]*CLI_SOCKET_PATH[[:space:]]*=/ {gsub(/^[[:space:]]+|[[:space:]]+$/, "", $2); print $2; exit}' /etc/uce/settings.cfg)
	if [[ -n "${configured_socket:-}" ]]; then
		default_socket="$configured_socket"
	fi
fi
socket_path="${UCE_CLI_SOCKET:-$default_socket}"
method="auto"
raw_json=""

usage() {
	cat <<'USAGE'
Usage:
  scripts/uce-cli [options] <unit-or-hook> [key=value ...]

Options:
  --socket PATH     Unix socket path (default: CLI_SOCKET_PATH from /etc/uce/settings.cfg,
                    UCE_CLI_SOCKET, or /run/uce/cli.sock)
  --get             Send key=value parameters as a query string
  --post            Send key=value parameters as a JSON POST (default when params exist)
  --json JSON       Send raw JSON as POST body
  -h, --help        Show this help

Examples:
  scripts/uce-cli /ping
  scripts/uce-cli /tests/cli.uce action=echo message=hello
  scripts/uce-cli --json '{"action":"echo","message":"hello"}' /tests/cli.uce
  scripts/uce-cli --get /tests/cli.uce action=echo message=hello
USAGE
}

while [[ $# -gt 0 ]]; do
	case "$1" in
		--socket)
			[[ $# -ge 2 ]] || { echo "--socket requires a path" >&2; exit 2; }
			socket_path="$2"
			shift 2
			;;
		--get)
			method="get"
			shift
			;;
		--post)
			method="post"
			shift
			;;
		--json)
			[[ $# -ge 2 ]] || { echo "--json requires a JSON value" >&2; exit 2; }
			raw_json="$2"
			method="post"
			shift 2
			;;
		-h|--help)
			usage
			exit 0
			;;
		--)
			shift
			break
			;;
		-*)
			echo "unknown option: $1" >&2
			usage >&2
			exit 2
			;;
		*)
			break
			;;
	esac
done

[[ $# -ge 1 ]] || { usage >&2; exit 2; }
path="$1"
shift

if [[ "$path" != /* ]]; then
	path="/$path"
fi

if [[ ! -S "$socket_path" ]]; then
	echo "UCE CLI socket not found: $socket_path" >&2
	exit 1
fi

if [[ "$method" == "auto" ]]; then
	if [[ $# -gt 0 || -n "$raw_json" ]]; then
		method="post"
	else
		method="get"
	fi
fi

if [[ -n "$raw_json" ]]; then
	printf '%s' "$raw_json" | python3 -m json.tool >/dev/null
	curl -sS --fail-with-body --unix-socket "$socket_path" \
		-X POST \
		-H 'Content-Type: application/json' \
		--data-binary "$raw_json" \
		"http://localhost$path"
	exit $?
fi

if [[ "$method" == "get" ]]; then
	url="http://localhost$path"
	if [[ $# -gt 0 ]]; then
		query=$(python3 - "$@" <<'PY'
import sys, urllib.parse
pairs = []
for arg in sys.argv[1:]:
    if '=' not in arg:
        raise SystemExit(f"argument is not key=value: {arg}")
    key, value = arg.split('=', 1)
    pairs.append((key, value))
print(urllib.parse.urlencode(pairs))
PY
)
		url="$url?$query"
	fi
	curl -sS --fail-with-body --unix-socket "$socket_path" "$url"
else
	json=$(python3 - "$@" <<'PY'
import json, sys
payload = {}
for arg in sys.argv[1:]:
    if '=' not in arg:
        raise SystemExit(f"argument is not key=value: {arg}")
    key, value = arg.split('=', 1)
    lowered = value.lower()
    if lowered == 'true':
        parsed = True
    elif lowered == 'false':
        parsed = False
    elif lowered in ('null', 'none'):
        parsed = None
    else:
        try:
            parsed = int(value)
        except ValueError:
            try:
                parsed = float(value)
            except ValueError:
                parsed = value
    payload[key] = parsed
print(json.dumps(payload, separators=(',', ':')))
PY
)
	curl -sS --fail-with-body --unix-socket "$socket_path" \
		-X POST \
		-H 'Content-Type: application/json' \
		--data-binary "$json" \
		"http://localhost$path"
fi
