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

usage() {
  cat <<'EOF'
Usage: Scripts/forgejo-dispatch-via-host.sh <workflow> [--ref <ref>] [--inputs <json>] [--inputs-file <path>] [--return-run-info]

Dispatch a Burrow Forgejo workflow by SSHing to the live forge host and using
the managed dispatcher token from the host runtime.

Environment:
  FORGEJO_BASE_URL                         Default: https://git.burrow.net
  FORGEJO_REPO                             Default: hackclub/burrow
  BURROW_FORGE_HOST                        Default: root@git.burrow.net
  BURROW_FORGE_HOST_ADDRESS                Optional SSH HostName override
  BURROW_FORGE_SSH_KEY                     Optional explicit SSH private key
  AGE_FORGE_SSH_KEY                        Optional injected SSH private key material
  BURROW_FORGE_DISPATCHER_CONFIG_FILE      Default: /run/agenix/burrowForgejoNscDispatcherConfig
EOF
}

base_url="${FORGEJO_BASE_URL:-https://git.burrow.net}"
repo_slug="${FORGEJO_REPO:-hackclub/burrow}"
forge_host="${BURROW_FORGE_HOST:-root@git.burrow.net}"
forge_host_address="${BURROW_FORGE_HOST_ADDRESS:-}"
dispatcher_config_file="${BURROW_FORGE_DISPATCHER_CONFIG_FILE:-/run/agenix/burrowForgejoNscDispatcherConfig}"
workflow=""
ref="main"
inputs_json=""
return_run_info="false"

while [[ $# -gt 0 ]]; do
  case "$1" in
    -h|--help)
      usage
      exit 0
      ;;
    --ref)
      ref="${2:-}"
      shift 2
      ;;
    --inputs)
      inputs_json="${2:-}"
      shift 2
      ;;
    --inputs-file)
      inputs_json="$(cat "${2:-}")"
      shift 2
      ;;
    --return-run-info)
      return_run_info="true"
      shift
      ;;
    *)
      if [[ -z "$workflow" ]]; then
        workflow="$1"
        shift
      else
        echo "Unexpected argument: $1" >&2
        usage >&2
        exit 64
      fi
      ;;
  esac
done

if [[ -z "$workflow" ]]; then
  echo "Missing workflow name or file, for example build-release.yml." >&2
  usage >&2
  exit 64
fi

script_dir="$(CDPATH= cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
resolved_forge_ssh_key="$("${script_dir}/resolve-forge-ssh-key.sh")"
eval "$resolved_forge_ssh_key"
ssh_key="${BURROW_FORGE_SSH_KEY}"

if [[ -n "$inputs_json" ]]; then
  if ! python3 - "$inputs_json" <<'PY' >/dev/null
import json
import sys

value = json.loads(sys.argv[1])
if not isinstance(value, dict):
    raise SystemExit(1)
PY
  then
    echo "--inputs must be a JSON object." >&2
    exit 64
  fi
fi

workflow_path="$(python3 - "$workflow" <<'PY'
import sys
import urllib.parse

print(urllib.parse.quote(sys.argv[1], safe=""))
PY
)"

payload="$(python3 - "$ref" "$inputs_json" "$return_run_info" <<'PY'
import json
import sys

ref = sys.argv[1]
inputs_arg = sys.argv[2]
return_run_info = sys.argv[3] == "true"

payload = {"ref": ref}
if inputs_arg:
    inputs = json.loads(inputs_arg)
    payload["inputs"] = {key: str(value) for key, value in inputs.items()}
if return_run_info:
    payload["return_run_info"] = True
print(json.dumps(payload))
PY
)"

payload_b64="$(python3 - "$payload" <<'PY'
import base64
import sys

print(base64.b64encode(sys.argv[1].encode()).decode())
PY
)"

ssh_opts=(
  -i "$ssh_key"
  -o IdentitiesOnly=yes
  -o UserKnownHostsFile=/dev/null
  -o GlobalKnownHostsFile=/dev/null
  -o StrictHostKeyChecking=accept-new
)
if [[ -n "$forge_host_address" ]]; then
  ssh_opts+=(-o "HostName=$forge_host_address")
fi

response="$(
  ssh "${ssh_opts[@]}" "$forge_host" bash -s -- \
    "$base_url" "$repo_slug" "$workflow_path" "$dispatcher_config_file" "$payload_b64" <<'EOF'
set -euo pipefail

base_url="$1"
repo_slug="$2"
workflow_path="$3"
dispatcher_config_file="$4"
payload_b64="$5"

payload="$(python3 - "$payload_b64" <<'PY'
import base64
import sys

print(base64.b64decode(sys.argv[1]).decode())
PY
)"

if [[ ! -s "$dispatcher_config_file" ]]; then
  echo "Forge dispatcher config is missing or empty: $dispatcher_config_file" >&2
  exit 1
fi

runtime_token="$(
  awk '
    /^[A-Za-z0-9_-]+:/ { in_forgejo = ($0 ~ /^forgejo:/); next }
    in_forgejo && /^[[:space:]]+token:/ {
      sub(/^[[:space:]]+token:[[:space:]]*/, "")
      gsub(/^"/, "")
      gsub(/"$/, "")
      gsub(/^\047/, "")
      gsub(/\047$/, "")
      print
      exit
    }
  ' "$dispatcher_config_file" | tr -d "\r\n"
)"

if [[ -z "$runtime_token" ]]; then
  echo "Forge dispatcher token not found in $dispatcher_config_file" >&2
  exit 1
fi

url="${base_url%/}/api/v1/repos/${repo_slug}/actions/workflows/${workflow_path}/dispatches"
response_file="$(mktemp)"
http_code="$(
  curl -sS -o "$response_file" -w '%{http_code}' -X POST \
    -H "Authorization: token ${runtime_token}" \
    -H "Content-Type: application/json" \
    --data-binary "$payload" \
    "$url"
)"
if [[ "$http_code" != 2* ]]; then
  cat "$response_file" >&2
  rm -f "$response_file"
  exit 22
fi
cat "$response_file"
rm -f "$response_file"
EOF
)"

if [[ "$return_run_info" == "true" ]]; then
  printf '%s\n' "$response"
else
  echo "Dispatched ${workflow} on ${ref} via ${forge_host}."
fi
