#!/usr/bin/env bash
# Regression harness for issue-create.sh Markdown-body safety (#559).
#
# Guards against reintroduction of eval-based command construction. The wrapper
# builds its tea/gh invocation as an argv array, so a body containing command
# substitution ($(...)), backticks, quotes, and dollar signs MUST reach tea
# verbatim and MUST NOT be shell-evaluated. This test asserts both:
#   1. No command-substitution side effect (an injected `touch SENTINEL` never runs).
#   2. The --description value tea receives is byte-for-byte the original body.

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
WORK_DIR="${MOSAIC_TEST_WORK_DIR:-$PWD/.mosaic-test-work/issue-create-body-safety}"
REPO_DIR="$WORK_DIR/repo"
BIN_DIR="$WORK_DIR/bin"
SENTINEL="$WORK_DIR/INJECTION_SENTINEL"
BODY_FILE="$WORK_DIR/body.txt"
RECEIVED_FILE="$WORK_DIR/received-description.txt"

rm -rf "$WORK_DIR"
mkdir -p "$REPO_DIR" "$BIN_DIR"

git -C "$REPO_DIR" init -q
git -C "$REPO_DIR" remote add origin https://git.mosaicstack.dev/mosaicstack/stack.git

# Hostile Markdown body. The unquoted heredoc expands $SENTINEL (a real path we
# want embedded) but every shell metacharacter we care about is backslash-escaped
# so the TEST shell writes them literally into the file — the bytes the wrapper
# must then preserve.
cat > "$BODY_FILE" <<EOF
# Release notes

Inline code: \`rm -rf /\` must stay literal.
Command sub attempt: \$(touch $SENTINEL)
Backtick cmd attempt: \`touch $SENTINEL\`
Dollars: \$HOME \${PATH} \$5.00 and 100% done
Quotes: "double" and 'single' and \`mixed\`
Trailing pipe-ish: foo | bar && baz ; qux
EOF

BODY="$(cat "$BODY_FILE")"

# Mock tea: resolve a mosaicstack login, then capture the --description verbatim.
cat > "$BIN_DIR/tea" <<'SH'
#!/usr/bin/env bash
set -euo pipefail

if [[ "$*" == "login list --output json" ]]; then
    cat <<'JSON'
[
  {"name":"mosaicstack","url":"https://git.mosaicstack.dev","user":"ci-bot"}
]
JSON
    exit 0
fi

if [[ "${1:-}" == "api" ]]; then
    printf '%s\n' '{"login":"ci-bot"}'
    exit 0
fi

if [[ "${1:-}" == "issue" && "${2:-}" == "create" ]]; then
    desc=""
    while [[ $# -gt 0 ]]; do
        case "$1" in
            --description) desc="$2"; shift 2 ;;
            *) shift ;;
        esac
    done
    printf '%s' "$desc" > "$MOSAIC_TEST_RECEIVED"
    echo "#1 created"
    exit 0
fi

exit 0
SH
chmod +x "$BIN_DIR/tea"

(
    cd "$REPO_DIR"
    PATH="$BIN_DIR:$PATH" \
    MOSAIC_TEST_RECEIVED="$RECEIVED_FILE" \
    "$SCRIPT_DIR/issue-create.sh" -t "Body safety test" -b "$BODY"
) >/dev/null

# 1. No command substitution executed anywhere in the pipeline.
if [[ -e "$SENTINEL" ]]; then
    echo "FAIL: injected command substitution executed (sentinel file created): $SENTINEL" >&2
    exit 1
fi

# 2. tea actually received the body (issue create path taken, not silently dropped).
if [[ ! -f "$RECEIVED_FILE" ]]; then
    echo "FAIL: tea issue create was never invoked with a --description" >&2
    exit 1
fi

# 3. The description tea received is byte-for-byte the original body.
if [[ "$(cat "$RECEIVED_FILE")" != "$BODY" ]]; then
    echo "FAIL: body was not preserved verbatim through issue-create.sh" >&2
    echo "--- expected ---" >&2; printf '%s\n' "$BODY" >&2
    echo "--- received ---" >&2; cat "$RECEIVED_FILE" >&2
    exit 1
fi

echo "issue-create.sh Markdown body-safety regression harness passed"
