#!/usr/bin/env bash
# nukez_helpers.sh - optional shell helpers for Nukez HTTP workflows.
#
# Dependencies:
#   - curl, jq
#   - node 18+ or bun for nukez_sign.mjs, OR python3+openssl for nukez_sign.py
#   - a Solana CLI keypair JSON for signed-envelope calls
#
# This helper is for local development, docs, smoke tests, and agent workflows.
# It is not a browser SDK and does not hide the underlying HTTP protocol.

BASE="${BASE:-https://api.nukez.xyz}"
SOL_KEYPAIR="${SOL_KEYPAIR:-$HOME/.keys/delegators/svm_key.json}"

if [ -n "${BASH_SOURCE[0]:-}" ]; then
  _NUKEZ_HELPERS_FILE="${BASH_SOURCE[0]}"
elif [ -n "${ZSH_VERSION:-}" ]; then
  eval '_NUKEZ_HELPERS_FILE="${(%):-%x}"'
else
  _NUKEZ_HELPERS_FILE="$0"
fi

_NUKEZ_HELPERS_DIR="$(cd "$(dirname "$_NUKEZ_HELPERS_FILE")" && pwd)"
NUKEZ_SIGN_JS="${NUKEZ_SIGN_JS:-$_NUKEZ_HELPERS_DIR/nukez_sign.mjs}"
NUKEZ_SIGN_PY="${NUKEZ_SIGN_PY:-$_NUKEZ_HELPERS_DIR/nukez_sign.py}"

if command -v bun >/dev/null 2>&1 && [ -f "$NUKEZ_SIGN_JS" ]; then
  NUKEZ_SIGN_MODE="${NUKEZ_SIGN_MODE:-js}"
  NUKEZ_RUNTIME="bun"
elif command -v node >/dev/null 2>&1 && [ -f "$NUKEZ_SIGN_JS" ]; then
  NUKEZ_SIGN_MODE="${NUKEZ_SIGN_MODE:-js}"
  NUKEZ_RUNTIME="node"
elif command -v python3 >/dev/null 2>&1 && [ -f "$NUKEZ_SIGN_PY" ]; then
  NUKEZ_SIGN_MODE="${NUKEZ_SIGN_MODE:-py}"
  NUKEZ_RUNTIME="python3"
else
  NUKEZ_SIGN_MODE=""
  NUKEZ_RUNTIME=""
fi

die() {
  echo "ERROR: $*" >&2
  return 1
}

show_json() {
  local s="${1:-}"
  if printf '%s' "$s" | jq -e . >/dev/null 2>&1; then
    printf '%s' "$s" | jq .
  else
    printf '%s\n' "$s"
  fi
}

has_error() {
  local s="${1:-}"
  printf '%s' "$s" | jq -e . >/dev/null 2>&1 || return 0
  printf '%s' "$s" | jq -e '(.error_code? // .error? // "") | tostring | length > 0' >/dev/null 2>&1
}

stable_locker_id() {
  printf 'locker_%s\n' "$(printf '%s' "$1" | shasum -a 256 | cut -c1-12)"
}

_sign_envelope() {
  local method="$1"
  local req_path="$2"
  local ops_json="$3"
  local body="${4:-}"

  [ -n "$RECEIPT_ID" ] || die "RECEIPT_ID must be set"
  [ -f "$SOL_KEYPAIR" ] || die "SOL_KEYPAIR not found: $SOL_KEYPAIR"

  if [ "$NUKEZ_SIGN_MODE" = "js" ]; then
    if [ -n "$body" ]; then
      printf '%s' "$body" | "$NUKEZ_RUNTIME" "$NUKEZ_SIGN_JS" \
        --keypair "$SOL_KEYPAIR" \
        --method "$method" \
        --path "$req_path" \
        --receipt-id "$RECEIPT_ID" \
        --ops "$ops_json"
    else
      "$NUKEZ_RUNTIME" "$NUKEZ_SIGN_JS" \
        --keypair "$SOL_KEYPAIR" \
        --method "$method" \
        --path "$req_path" \
        --receipt-id "$RECEIPT_ID" \
        --ops "$ops_json"
    fi
  elif [ "$NUKEZ_SIGN_MODE" = "py" ]; then
    if [ -n "$body" ]; then
      printf '%s' "$body" | python3 "$NUKEZ_SIGN_PY" \
        --keypair "$SOL_KEYPAIR" \
        --method "$method" \
        --path "$req_path" \
        --receipt-id "$RECEIPT_ID" \
        --ops "$ops_json"
    else
      python3 "$NUKEZ_SIGN_PY" \
        --keypair "$SOL_KEYPAIR" \
        --method "$method" \
        --path "$req_path" \
        --receipt-id "$RECEIPT_ID" \
        --ops "$ops_json"
    fi
  else
    die "no signer available; place nukez_sign.mjs or nukez_sign.py next to this file"
  fi
}

# signed_call METHOD PATH OPS_JSON [BODY]
#
# Examples:
#   signed_call POST "/v1/storage/signed_provision" '["locker:provision"]' '{"receipt_id":"abc","tags":[]}'
#   signed_call GET  "/v1/lockers/locker_abc/files" '["locker:list"]'
#   signed_call GET  "/v1/lockers/locker_abc/record" '["locker:read"]'
signed_call() {
  local method="$1"
  local req_path="$2"
  local ops_json="$3"
  local body="${4:-}"
  local sign_output x_env x_sig url

  sign_output="$(_sign_envelope "$method" "$req_path" "$ops_json" "$body")" || {
    printf '%s\n' "$sign_output" >&2
    return 1
  }

  x_env="$(printf '%s' "$sign_output" | jq -r '.x_dl_envelope')"
  x_sig="$(printf '%s' "$sign_output" | jq -r '.x_dl_signature')"
  url="${BASE}${req_path}"

  case "$method" in
    GET|HEAD|DELETE)
      curl -sS -X "$method" "$url" \
        -H "X-Nukez-Envelope: $x_env" \
        -H "X-Nukez-Signature: $x_sig"
      ;;
    *)
      curl -sS -X "$method" "$url" \
        -H "Content-Type: application/json" \
        -H "X-Nukez-Envelope: $x_env" \
        -H "X-Nukez-Signature: $x_sig" \
        -d "$body"
      ;;
  esac
}

# select_payment RESP_JSON [NETWORK] [ASSET]
# Prints the selected accepts[] leg as compact JSON.
select_payment() {
  local resp="$1"
  local network="${2:-${PAY_NETWORK:-solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp}}"
  local asset="${3:-${PAY_ASSET:-SOL}}"
  printf '%s' "$resp" | jq -c --arg network "$network" --arg asset "$asset" \
    '.accepts[] | select(.network == $network and .extra.name == $asset)' | head -n 1
}

# upload_file LOCKER_ID FILENAME LOCAL_PATH [CONTENT_TYPE]
# Creates a file URL, uploads bytes, then POSTs confirm_url when present.
upload_file() {
  local locker_id="$1"
  local filename="$2"
  local local_path="$3"
  local content_type="${4:-application/octet-stream}"

  [ -f "$local_path" ] || die "file not found: $local_path" || return 1

  local body resp upload_url confirm_url size http_code
  body="$(jq -cS -n --arg fn "$filename" --arg ct "$content_type" \
    '{filename:$fn, content_type:$ct, ttl_min:30}')"
  resp="$(signed_call POST "/v1/lockers/${locker_id}/files" '["locker:write"]' "$body")" || return 1
  if has_error "$resp"; then
    show_json "$resp" >&2
    return 1
  fi

  upload_url="$(printf '%s' "$resp" | jq -r '.upload_url')"
  confirm_url="$(printf '%s' "$resp" | jq -r '.confirm_url // empty')"
  size="$(wc -c < "$local_path" | tr -d ' ')"

  if [ "$size" -gt 33554432 ]; then
    local resolved_url
    resolved_url="$(curl -sS -o /dev/null -w '%{redirect_url}' \
      -X PUT -H "Content-Type: $content_type" "$upload_url")"
    [ -n "$resolved_url" ] || die "could not resolve upload redirect" || return 1
    http_code="$(curl -sS -o /dev/null -w '%{http_code}' \
      -X PUT -H "Content-Type: $content_type" --data-binary "@${local_path}" "$resolved_url")"
  else
    http_code="$(curl -sS -o /dev/null -w '%{http_code}' \
      -L --request PUT -H "Content-Type: $content_type" --data-binary "@${local_path}" "$upload_url")"
  fi

  [ "$http_code" = "200" ] || die "upload returned HTTP $http_code" || return 1

  if [ -n "$confirm_url" ]; then
    curl -sS -X POST "$confirm_url" | jq .
  fi
}

_nukez_preflight() {
  local ok=true
  for bin in curl jq; do
    if ! command -v "$bin" >/dev/null 2>&1; then
      echo "MISSING: $bin" >&2
      ok=false
    fi
  done
  if [ -z "$NUKEZ_RUNTIME" ]; then
    echo "MISSING: node/bun+nukez_sign.mjs or python3+nukez_sign.py" >&2
    ok=false
  fi
  if [ ! -f "$SOL_KEYPAIR" ]; then
    echo "WARNING: SOL_KEYPAIR not found: $SOL_KEYPAIR" >&2
  fi
  if $ok; then
    echo "nukez_helpers loaded | runtime=$NUKEZ_RUNTIME | mode=$NUKEZ_SIGN_MODE | BASE=$BASE | keypair=$(basename "$SOL_KEYPAIR")"
  fi
}

_nukez_preflight
