#!/usr/bin/env bash
# fakturnia — a tiny curl wrapper for the Fakturnia External REST API with
# built-in OAuth 2.0 (client credentials). Like `curl`, but it fetches, caches
# and attaches the bearer token for you. No dependencies beyond curl + coreutils.
#
#   Install:  curl -fsSL https://developers.fakturnia.pl/fakturnia.sh -o fakturnia && chmod +x fakturnia
#   Configure (defaults to the sandbox — switch to production deliberately):
#     export FAKTURNIA_CLIENT_ID=client_...
#     export FAKTURNIA_CLIENT_SECRET=secret_...
#     export FAKTURNIA_ENV=sandbox        # or: production
#
#   Usage:
#     ./fakturnia token                                   # print a bearer token
#     ./fakturnia GET  /documents/                        # list documents
#     ./fakturnia GET  /documents/<id>/download           # (binary) invoice PDF
#     ./fakturnia POST /documents/ '{"documentType":"FakturaVAT", ...}'
#     ./fakturnia POST /documents/<id>/send-to-ksef
#
set -euo pipefail

: "${FAKTURNIA_CLIENT_ID:?set FAKTURNIA_CLIENT_ID}"
: "${FAKTURNIA_CLIENT_SECRET:?set FAKTURNIA_CLIENT_SECRET}"
ENVIRONMENT="${FAKTURNIA_ENV:-sandbox}"

case "$ENVIRONMENT" in
  production) API="https://prod.api.fakturnia.pl" ;;
  sandbox)    API="https://sandbox.api.fakturnia.pl" ;;
  *) echo "FAKTURNIA_ENV must be 'sandbox' or 'production' (got '$ENVIRONMENT')" >&2; exit 1 ;;
esac
BASE="$API/external/v1"
TOKEN_URL="$API/v1/oauth/token"
CACHE="${TMPDIR:-/tmp}/fakturnia-token-$ENVIRONMENT"

# Minimal JSON scalar extraction so the script needs no `jq`.
json_str() { sed -n "s/.*\"$1\"[[:space:]]*:[[:space:]]*\"\([^\"]*\)\".*/\1/p"; }
json_num() { sed -n "s/.*\"$1\"[[:space:]]*:[[:space:]]*\([0-9]*\).*/\1/p"; }

get_token() {
  if [ -f "$CACHE" ]; then
    local cached_exp cached_tok now
    cached_tok="$(sed -n 1p "$CACHE")"
    cached_exp="$(sed -n 2p "$CACHE")"
    now="$(date +%s)"
    if [ -n "$cached_tok" ] && [ -n "$cached_exp" ] && [ "$cached_exp" -gt "$((now + 60))" ]; then
      printf '%s' "$cached_tok"; return
    fi
  fi
  local resp tok exp
  resp="$(curl -fsS "$TOKEN_URL" -H 'Content-Type: application/json' \
    -d "{\"grant_type\":\"client_credentials\",\"client_id\":\"$FAKTURNIA_CLIENT_ID\",\"client_secret\":\"$FAKTURNIA_CLIENT_SECRET\"}")"
  tok="$(printf '%s' "$resp" | json_str access_token)"
  exp="$(printf '%s' "$resp" | json_num expires_in)"
  [ -n "$tok" ] || { echo "token request failed: $resp" >&2; exit 1; }
  printf '%s\n%s\n' "$tok" "$(( $(date +%s) + ${exp:-3600} ))" > "$CACHE"
  printf '%s' "$tok"
}

new_idempotency_key() { uuidgen 2>/dev/null || cat /proc/sys/kernel/random/uuid 2>/dev/null || echo "cli-$$-$RANDOM$RANDOM"; }

cmd="${1:-}"
case "$cmd" in
  token)
    get_token; echo ;;
  ""|-h|--help)
    sed -n '2,20p' "$0" | sed 's/^# \{0,1\}//' ;;
  GET|HEAD|DELETE|POST|PUT|PATCH|get|head|delete|post|put|patch)
    method="$(printf '%s' "$cmd" | tr '[:lower:]' '[:upper:]')"
    route="${2:?path required, e.g. /documents/}"
    body="${3:-}"
    token="$(get_token)"
    set -- -fsS -X "$method" "$BASE$route" -H "Authorization: Bearer $token"
    if [ -n "$body" ]; then
      set -- "$@" -H 'Content-Type: application/json' -H "Idempotency-Key: $(new_idempotency_key)" -d "$body"
    fi
    curl "$@"; echo ;;
  *)
    echo "unknown command '$cmd' — use: fakturnia <METHOD> <path> [json] | fakturnia token" >&2; exit 1 ;;
esac
