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

BAZAAR_URL="${DEXTER_BAZAAR_URL:-https://x402.dexter.cash/discovery/resources}"
FACILITATOR_URL="${DEXTER_FACILITATOR_URL:-https://x402.dexter.cash}"

usage() {
  cat <<'EOF'
dexter-x402 CLI — search and price-check the Dexter x402 marketplace

USAGE:
  x402.sh search [QUERY]        Search APIs by keyword (optional filter)
  x402.sh check  URL            Check pricing for a specific endpoint
  x402.sh categories            List available API categories
  x402.sh facilitator           Show facilitator info and features
  x402.sh help                  Show this help message

ENVIRONMENT:
  DEXTER_BAZAAR_URL        Bazaar discovery endpoint (default: https://x402.dexter.cash/discovery/resources)
  DEXTER_FACILITATOR_URL   Facilitator URL (default: https://x402.dexter.cash)

EXAMPLES:
  x402.sh search "token price"
  x402.sh search
  x402.sh check https://pro-api.coingecko.com/api/v3/x402/coins/bitcoin
  x402.sh categories
  x402.sh facilitator
EOF
}

require_cmd() {
  command -v "$1" >/dev/null 2>&1 || { echo "Error: $1 is required but not installed." >&2; exit 1; }
}

format_usdc() {
  local raw="$1"
  local decimals="${2:-6}"
  python3 -c "print(f'\${int(\"$raw\") / (10 ** $decimals):.4f} USDC')" 2>/dev/null \
    || echo "${raw} atomic units"
}

cmd_search() {
  require_cmd curl
  require_cmd jq

  local limit=30
  local raw
  raw=$(curl -sf "${BAZAAR_URL}?limit=${limit}" 2>/dev/null) || {
    echo "Error: could not reach bazaar at ${BAZAAR_URL}" >&2
    exit 1
  }

  local query="${1:-}"

  if [ -n "$query" ]; then
    echo "$raw" | jq -r --arg q "$query" '
      ($q | ascii_downcase) as $lq |
      [.items[] |
        ((.description // "") + " " + (.resource // "")) as $haystack |
        select(($lq | split(" ") | all(. as $w | ($haystack | ascii_downcase | test($w)))))
      ]
      | to_entries[]
      | "\(.key + 1). [\(.value.method // "GET")] \(.value.resource)"
        + "\n   \(.value.description // "No description")"
        + "\n   Price: \(.value.accepts[0].maxAmountRequired // .value.accepts[0].amount // "unknown") | Network: \(.value.accepts[0].network // "unknown")"
        + "\n"
    '
  else
    echo "$raw" | jq -r '
      .items
      | to_entries[]
      | "\(.key + 1). [\(.value.method // "GET")] \(.value.resource)"
        + "\n   \(.value.description // "No description")"
        + "\n   Price: \(.value.accepts[0].maxAmountRequired // .value.accepts[0].amount // "unknown") | Network: \(.value.accepts[0].network // "unknown")"
        + "\n"
    '
  fi
}

cmd_check() {
  require_cmd curl
  require_cmd jq

  local url="${1:?Error: provide a URL to check}"

  echo "Probing ${url} ..."

  local tmpfile
  tmpfile=$(mktemp)
  local http_code
  http_code=$(curl -s -w "%{http_code}" -D "${tmpfile}.headers" -o "${tmpfile}.body" "$url" 2>/dev/null)

  if [ "$http_code" = "402" ]; then
    echo "Status: 402 Payment Required"
    echo ""

    # Try JSON body first (most common), then Payment-Required header, then base64 header
    local pricing=""

    # Source 1: JSON body with accepts array
    if [ -s "${tmpfile}.body" ] && jq -e '.accepts' "${tmpfile}.body" >/dev/null 2>&1; then
      pricing="${tmpfile}.body"
    fi

    # Source 2: Payment-Required header (raw JSON or base64)
    if [ -z "$pricing" ] && [ -f "${tmpfile}.headers" ]; then
      local pay_header
      pay_header=$(grep -i "payment-required" "${tmpfile}.headers" 2>/dev/null | sed 's/^[^:]*: //' | tr -d '\r\n')
      if [ -n "$pay_header" ]; then
        # Try raw JSON
        if echo "$pay_header" | jq -e '.accepts' >/dev/null 2>&1; then
          echo "$pay_header" > "${tmpfile}.parsed"
          pricing="${tmpfile}.parsed"
        else
          # Try base64 decode
          local decoded
          decoded=$(echo "$pay_header" | base64 -d 2>/dev/null)
          if [ -n "$decoded" ] && echo "$decoded" | jq -e '.accepts' >/dev/null 2>&1; then
            echo "$decoded" > "${tmpfile}.parsed"
            pricing="${tmpfile}.parsed"
          fi
        fi
      fi
    fi

    if [ -n "$pricing" ]; then
      local version
      version=$(jq -r '.x402Version // "unknown"' "$pricing")
      echo "x402 Version: ${version}"
      echo ""
      echo "Payment options:"
      jq -r '
        .accepts[]
        | "  Scheme:  \(.scheme)"
        + "\n  Network: \(.network)"
        + "\n  Amount:  \(.maxAmountRequired // .amount // "unknown") atomic units"
        + "\n  Asset:   \(.asset)"
        + "\n  PayTo:   \(.payTo)"
        + (if .extra.feePayer then "\n  FeePay:  \(.extra.feePayer)" else "" end)
        + "\n"
      ' "$pricing"
    else
      echo "Could not parse payment requirements from response."
      echo "Raw body:"
      head -c 500 "${tmpfile}.body" 2>/dev/null
    fi
  elif [ "$http_code" = "200" ]; then
    echo "Status: 200 OK — this endpoint is free (no payment required)"
  else
    echo "Status: ${http_code:-unknown}"
    echo "This may not be an x402 endpoint, or it may be unreachable."
  fi

  rm -f "$tmpfile" "${tmpfile}.headers" "${tmpfile}.body" "${tmpfile}.parsed" 2>/dev/null
}

cmd_categories() {
  require_cmd curl
  require_cmd jq

  local raw
  raw=$(curl -sf "${BAZAAR_URL}?limit=200" 2>/dev/null) || {
    echo "Error: could not reach bazaar at ${BAZAAR_URL}" >&2
    exit 1
  }

  local total
  total=$(echo "$raw" | jq '.items | length')

  echo "Dexter x402 Marketplace — ${total} endpoints"
  echo ""
  echo "Categories (based on endpoint descriptions):"
  echo ""
  echo "  DeFi          — Token prices, swap quotes, protocol rankings, liquidity data"
  echo "  AI            — LLM inference, embeddings, image generation, chat models"
  echo "  Analytics     — Wallet scoring, token metrics, on-chain analysis"
  echo "  Social        — Twitter/X profiles, engagement metrics, social data"
  echo "  Data          — Market data, historical prices, blockchain events"
  echo "  Tools         — Transcription, translation, code analysis, utilities"
  echo "  Infrastructure — RPC access, node data, block explorers"
  echo "  Trading       — DEX aggregation, order execution, position management"
  echo ""
  echo "Networks:"
  echo "$raw" | jq -r '
    [.items[].accepts[].network]
    | group_by(.)
    | map({network: .[0], count: length})
    | sort_by(-.count)[]
    | "  \(.network): \(.count) endpoints"
  '
}

cmd_facilitator() {
  require_cmd curl
  require_cmd jq

  echo "Querying facilitator at ${FACILITATOR_URL} ..."
  echo ""

  local supported
  supported=$(curl -sf "${FACILITATOR_URL}/supported" 2>/dev/null) || {
    echo "Error: could not reach facilitator" >&2
    exit 1
  }

  echo "$supported" | jq -r '
    "Supported networks and features:",
    "",
    (.kinds[] | "  \(.network) (\(.scheme) scheme, x402 v\(.x402Version))"
      + (if .extra.features then
           "\n    Features: " + ([.extra.features | to_entries[] | select(.value == true) | .key] | join(", "))
         else "" end)
      + (if .extra.feePayer then "\n    Fee payer: \(.extra.feePayer)" else "" end)
    ),
    "",
    "Extensions: \(.extensions | join(", "))"
  '
}

case "${1:-help}" in
  search)     shift; cmd_search "$@" ;;
  check)      shift; cmd_check "$@" ;;
  categories) cmd_categories ;;
  facilitator) cmd_facilitator ;;
  help|--help|-h) usage ;;
  *) echo "Unknown command: $1" >&2; usage; exit 1 ;;
esac
