#!/usr/bin/env bash
# Storaged cap smoke — verifies ADR-002's per-prefix PUT cap.
#
# What it asserts:
#   1. 300 MiB PUT to _vectors/<key>          → 200 (cap raised to 4 GiB)
#   2. 300 MiB PUT to datasets/<key>          → 413 (default 256 MiB cap)
#   3. Round-trip read: 300 MiB GET from _vectors/<key>
#      sha-matches what we PUT (no truncation)
#
# Why this lives outside the main chain (just verify): it generates
# a 300 MiB payload, transfers it twice, takes ~5-10s on this box.
# Routine pre-push gating doesn't need that overhead — this smoke
# is opt-in via `just smoke-storaged-cap` after meaningful changes
# to storaged or vectord persistence.
#
# Usage: ./scripts/storaged_cap_smoke.sh

set -euo pipefail
cd "$(dirname "$0")/.."

export PATH="$PATH:/usr/local/go/bin"

PAYLOAD_MIB=300
VECTORS_KEY="_vectors/cap_smoke_$$.bin"
NONVECTORS_KEY="datasets/cap_smoke_$$.bin"

echo "[cap-smoke] building storaged + gateway..."
go build -o bin/ ./cmd/storaged ./cmd/gateway

pkill -f "bin/(storaged|gateway)" 2>/dev/null || true
sleep 0.3

PIDS=()
TMP="$(mktemp -d)"
PAYLOAD="$TMP/payload.bin"
ROUND_TRIP="$TMP/roundtrip.bin"

cleanup() {
    echo "[cap-smoke] cleanup"
    # Best-effort delete of test keys (404 is fine).
    curl -sS -m 5 -X DELETE "http://127.0.0.1:3110/v1/storage/delete/${VECTORS_KEY}" >/dev/null 2>&1 || true
    curl -sS -m 5 -X DELETE "http://127.0.0.1:3110/v1/storage/delete/${NONVECTORS_KEY}" >/dev/null 2>&1 || true
    for p in "${PIDS[@]}"; do [ -n "$p" ] && kill "$p" 2>/dev/null || true; done
    rm -rf "$TMP"
}
trap cleanup EXIT INT TERM

poll_health() {
    local port="$1" deadline=$(($(date +%s) + 5))
    while [ "$(date +%s)" -lt "$deadline" ]; do
        if curl -sS --max-time 1 "http://127.0.0.1:$port/health" >/dev/null 2>&1; then return 0; fi
        sleep 0.05
    done
    return 1
}

echo "[cap-smoke] launching storaged → gateway..."
./bin/storaged > "$TMP/storaged.log" 2>&1 &
PIDS+=($!)
poll_health 3211 || { echo "storaged failed"; tail -10 "$TMP/storaged.log"; exit 1; }

./bin/gateway > "$TMP/gateway.log" 2>&1 &
PIDS+=($!)
poll_health 3110 || { echo "gateway failed"; tail -10 "$TMP/gateway.log"; exit 1; }

echo "[cap-smoke] generating ${PAYLOAD_MIB} MiB deterministic payload..."
# /dev/zero gives all-zero bytes — deterministic across runs and
# machines, sha is stable, no pipe (avoids SIGPIPE under pipefail).
dd if=/dev/zero of="$PAYLOAD" bs=1M count="$PAYLOAD_MIB" status=none
EXPECTED_SIZE=$(stat -c%s "$PAYLOAD")
EXPECTED_SHA=$(sha256sum "$PAYLOAD" | awk '{print $1}')
echo "  size=$EXPECTED_SIZE sha=${EXPECTED_SHA:0:12}..."

FAILED=0

# ── Test 1: PUT 300 MiB to _vectors/ → 200 (was 413 before ADR-002) ──
echo "[cap-smoke] Test 1: PUT ${PAYLOAD_MIB} MiB to _vectors/ (should pass)"
HTTP=$(curl -sS -X PUT \
    --upload-file "$PAYLOAD" \
    -H "Content-Type: application/octet-stream" \
    -o "$TMP/put_vectors.body" \
    -w "%{http_code}" \
    "http://127.0.0.1:3110/v1/storage/put/${VECTORS_KEY}")
if [ "$HTTP" = "200" ]; then
    echo "  ✓ PUT _vectors/ → 200"
else
    echo "  ✗ PUT _vectors/ → $HTTP (expected 200; ADR-002 cap fix may have regressed)"
    cat "$TMP/put_vectors.body"; echo
    FAILED=1
fi

# ── Test 2: PUT same payload to datasets/ → 413 (default cap) ──
echo "[cap-smoke] Test 2: PUT ${PAYLOAD_MIB} MiB to datasets/ (should reject)"
HTTP=$(curl -sS -X PUT \
    --upload-file "$PAYLOAD" \
    -H "Content-Type: application/octet-stream" \
    -o /dev/null \
    -w "%{http_code}" \
    "http://127.0.0.1:3110/v1/storage/put/${NONVECTORS_KEY}")
if [ "$HTTP" = "413" ]; then
    echo "  ✓ PUT datasets/ → 413 (default cap protects routine prefixes)"
else
    echo "  ✗ PUT datasets/ → $HTTP (expected 413; default cap may be too permissive)"
    FAILED=1
fi

# ── Test 3: GET round-trip from _vectors/ — sha must match ──
echo "[cap-smoke] Test 3: GET _vectors/ — sha matches input"
curl -sS -o "$ROUND_TRIP" "http://127.0.0.1:3110/v1/storage/get/${VECTORS_KEY}"
ACTUAL_SHA=$(sha256sum "$ROUND_TRIP" | awk '{print $1}')
ACTUAL_SIZE=$(stat -c%s "$ROUND_TRIP")
if [ "$ACTUAL_SHA" = "$EXPECTED_SHA" ] && [ "$ACTUAL_SIZE" = "$EXPECTED_SIZE" ]; then
    echo "  ✓ GET round-trip preserves bytes (size=$ACTUAL_SIZE sha=${ACTUAL_SHA:0:12})"
else
    echo "  ✗ GET round-trip mismatch"
    echo "    expected size=$EXPECTED_SIZE sha=${EXPECTED_SHA:0:12}"
    echo "    actual   size=$ACTUAL_SIZE sha=${ACTUAL_SHA:0:12}"
    FAILED=1
fi

if [ "$FAILED" = "0" ]; then
    echo "[cap-smoke] ✓ Storaged cap smoke: PASSED"
    exit 0
else
    echo "[cap-smoke] ✗ Storaged cap smoke: FAILED"
    exit 1
fi
