#!/bin/sh
# Tests for scripts/rolling-upgrade.sh
#
# Tests flag parsing, error paths, and detection logic.
# Does not require a running server, network access, or root.
#
# Usage: ./tests/test_rolling_upgrade.sh
set -eu

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
UPGRADE_SCRIPT="$PROJECT_DIR/scripts/rolling-upgrade.sh"

passed=0
failed=0

fail() {
    echo "FAIL: $1"
    failed=$((failed + 1))
}

pass() {
    echo "PASS: $1"
    passed=$((passed + 1))
}

# --- Test: script is POSIX sh ---
test_posix_shebang() {
    first_line=$(head -1 "$UPGRADE_SCRIPT")
    if [ "$first_line" = "#!/bin/sh" ]; then
        pass "shebang is #!/bin/sh"
    else
        fail "shebang should be #!/bin/sh — got: $first_line"
    fi
}

# --- Test: script is executable ---
test_executable() {
    if [ -x "$UPGRADE_SCRIPT" ]; then
        pass "rolling-upgrade.sh is executable"
    else
        fail "rolling-upgrade.sh is not executable"
    fi
}

# --- Test: --help prints usage and exits 0 ---
test_help_flag() {
    output=$(sh "$UPGRADE_SCRIPT" --help 2>&1) || true
    if echo "$output" | grep -q "Usage:"; then
        pass "--help prints usage"
    else
        fail "--help should print usage — got: $output"
    fi
    if echo "$output" | grep -q "admin-url"; then
        pass "--help mentions --admin-url"
    else
        fail "--help should mention --admin-url"
    fi
    if echo "$output" | grep -q "deploy.md"; then
        pass "--help references deploy.md"
    else
        fail "--help should reference deploy.md"
    fi
}

# --- Test: exits with error when no admin key ---
test_no_admin_key() {
    output=$(FAFB_ADMIN_API_KEY="" sh "$UPGRADE_SCRIPT" 2>&1) || true
    if echo "$output" | grep -q "admin key required"; then
        pass "exits with error when no admin key"
    else
        fail "should require admin key — got: $output"
    fi
}

# --- Test: exits with error on unknown flag ---
test_unknown_flag() {
    output=$(FAFB_ADMIN_API_KEY="test" sh "$UPGRADE_SCRIPT" --bogus 2>&1) || true
    if echo "$output" | grep -q "unknown flag"; then
        pass "exits with error on unknown flag"
    else
        fail "should reject unknown flag — got: $output"
    fi
}

# --- Test: exits when server not reachable ---
test_server_not_reachable() {
    # Provide a stub binary so the script reaches the server health check
    # (without --binary the script tries to download a Linux tarball and
    # fails earlier on macOS with "unsupported OS").
    stub_bin="$(mktemp)"
    printf '#!/bin/sh\necho "fafb-q 0.0.0-stub"\n' > "$stub_bin"
    chmod +x "$stub_bin"
    output=$(FAFB_ADMIN_API_KEY="test" sh "$UPGRADE_SCRIPT" \
        --binary "$stub_bin" \
        --admin-url http://localhost:19999 2>&1) || true
    rm -f "$stub_bin"
    if echo "$output" | grep -qi "not reachable\|not ready"; then
        pass "exits when server not reachable"
    else
        fail "should fail when server not reachable — got: $output"
    fi
}

# --- Test: exits when --binary path doesn't exist ---
test_binary_not_found() {
    output=$(FAFB_ADMIN_API_KEY="test" sh "$UPGRADE_SCRIPT" --binary /nonexistent/fafb-q 2>&1) || true
    if echo "$output" | grep -q "not found or not executable"; then
        pass "exits when --binary path doesn't exist"
    else
        fail "should fail when binary missing — got: $output"
    fi
}

# --- Test: exits when --drain-timeout is not numeric ---
test_drain_timeout_not_numeric() {
    output=$(FAFB_ADMIN_API_KEY="test" sh "$UPGRADE_SCRIPT" --drain-timeout foo 2>&1) || true
    if echo "$output" | grep -q "requires a numeric value"; then
        pass "rejects non-numeric --drain-timeout"
    else
        fail "should reject non-numeric --drain-timeout — got: $output"
    fi
}

# --- Run all tests ---
echo "Running rolling-upgrade.sh tests..."
echo "---"

test_posix_shebang
test_executable
test_help_flag
test_no_admin_key
test_unknown_flag
test_drain_timeout_not_numeric
test_server_not_reachable
test_binary_not_found

echo "---"
echo "Results: $passed passed, $failed failed"

if [ "$failed" -gt 0 ]; then
    exit 1
fi
