#!/usr/bin/env bash

:<<'DOC'
Test-only HTTP stub for BATS. Source after lib/http.api.sh so this file
replaces http_request (no network).

  source "$SHELLOPS_DIR/lib/http.api.sh"
  source "$TEST_DIR/helpers/http_mock.bash"

Queue bodies with http_mock_enqueue / http_mock_enqueue_fail. Each http_request
consumes one response (FIFO). The queue is a temp file of one line per response:
compact JSON when the body is valid JSON, or a single line of raw text (e.g.
Forgejo raw file) otherwise. Multiline non-JSON bodies are not supported.
Dequeues persist when http_request runs inside command substitution (e.g.
graphql_request wraps it in $(...)); a pure in-memory queue would replay the
first response in every subshell.

Method + URL lines are appended to a log for assertions via http_mock_request_log.

http_get and http_post delegate to http_request, so the mock intercepts
them automatically. Parameters $3–$4 match the real http_request (body,
options) but are ignored unless you extend __http_mock__dispatch to match
on them.
DOC

__http_mock__ROOT=""
export __http_mock__QUEUE_FILE=""
export __http_mock__REQUEST_LOG=""

function http_mock_reset() {
  rm -rf "${__http_mock__ROOT:-}"
  __http_mock__ROOT="$(mktemp -d)"
  __http_mock__QUEUE_FILE="$__http_mock__ROOT/queue"
  __http_mock__REQUEST_LOG="$__http_mock__ROOT/requests.log"
  export __http_mock__QUEUE_FILE
  export __http_mock__REQUEST_LOG
  : > "$__http_mock__QUEUE_FILE"
  : > "$__http_mock__REQUEST_LOG"
}

function http_mock_enqueue() {
  local compact
  if compact="$(jq -e -c . <<< "$1" 2>/dev/null)"; then
    printf '%s\n' "$compact" >> "$__http_mock__QUEUE_FILE"
    return 0
  fi
  if [[ "$1" == *$'\n'* ]]; then
    error "http_mock_enqueue: non-JSON body must be a single line"
    return 1
  fi
  printf '%s\n' "$1" >> "$__http_mock__QUEUE_FILE"
}

function http_mock_enqueue_fail() {
  printf '%s\n' '{"__http_mock_fail__":true}' >> "$__http_mock__QUEUE_FILE"
}

function http_mock_enqueue_file() {
  local f="$1"
  http_mock_enqueue "$(cat "$f")"
}

function http_mock_request_log() {
  cat "$__http_mock__REQUEST_LOG"
}

function __http_mock__dispatch() {
  local method="$1" url="$2"
  local first rest

  printf '%s\n' "$method $url" >> "$__http_mock__REQUEST_LOG"

  if [[ ! -s "$__http_mock__QUEUE_FILE" ]]; then
    error "http_mock: empty queue (unexpected $method $url)"
    return 1
  fi

  first="$(head -n1 "$__http_mock__QUEUE_FILE")"
  rest="$(tail -n +2 "$__http_mock__QUEUE_FILE")"
  printf '%s' "$rest" > "$__http_mock__QUEUE_FILE"

  if [[ "$first" == '{"__http_mock_fail__":true}' ]]; then
    error "http_mock: simulated failure for $method $url"
    return 1
  fi

  printf '%s\n' "$first"
  return 0
}

function http_request() {
  __http_mock__dispatch "$@"
}

function http_upload() {
  __http_mock__dispatch "POST" "$1"
}

http_mock_reset
