#!/bin/bash
set -euo pipefail

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

# Read the project cache context.
CACHE_CONTEXT="$ROOT/project_cache_context.json"
PROJECT_CACHE_DIR=""
if [[ -f "$CACHE_CONTEXT" ]]; then
    PROJECT_CACHE_DIR="$(jq -r '.project_cache_dir // empty' "$CACHE_CONTEXT")"
fi

if [[ -z "$PROJECT_CACHE_DIR" || ! -d "$PROJECT_CACHE_DIR" ]]; then
    PROJECT_CACHE_DIR="$ROOT/artifacts/openziti"
    mkdir -p "$PROJECT_CACHE_DIR"
fi

REPO="$PROJECT_CACHE_DIR/repo"
GO_DIR="$PROJECT_CACHE_DIR/toolchain/go"
GO_BIN="$GO_DIR/bin/go"
MIRROR_DIR="$PROJECT_CACHE_DIR/repo-mirrors"

LOG_FILE="$LOGS/reproduction_steps.log"
exec > >(tee -a "$LOG_FILE") 2>&1

echo "=== CVE-2026-58165 Reproduction ==="
echo "ROOT=$ROOT"
echo "PROJECT_CACHE_DIR=$PROJECT_CACHE_DIR"
echo "REPO=$REPO"
echo "LOG_FILE=$LOG_FILE"

# Install Go if not present.
install_go() {
    if [[ -x "$GO_BIN" ]]; then
        "$GO_BIN" version
        return 0
    fi
    echo "Installing Go 1.26.4..."
    mkdir -p "$PROJECT_CACHE_DIR/toolchain"
    rm -rf "$GO_DIR"
    curl -fsSL "https://go.dev/dl/go1.26.4.linux-amd64.tar.gz" -o "$PROJECT_CACHE_DIR/toolchain/go.tar.gz"
    tar -xzf "$PROJECT_CACHE_DIR/toolchain/go.tar.gz" -C "$PROJECT_CACHE_DIR/toolchain"
    rm "$PROJECT_CACHE_DIR/toolchain/go.tar.gz"
    "$GO_BIN" version
}
install_go

export PATH="$GO_DIR/bin:$PATH"

# Clone or reuse the repo.
if [[ ! -d "$REPO/.git" ]]; then
    echo "Cloning openziti/ziti repository..."
    mkdir -p "$PROJECT_CACHE_DIR"
    git clone "https://github.com/openziti/ziti.git" "$REPO"
fi

VULN_COMMIT="3027fdffd3e57884487b7c46e5e669cfbc8becdf^"
FIXED_COMMIT="3027fdffd3e57884487b7c46e5e669cfbc8becdf"

echo "Resolving commits..."
cd "$REPO"
VULN_RESOLVED="$(git rev-parse "$VULN_COMMIT")"
FIXED_RESOLVED="$(git rev-parse "$FIXED_COMMIT")"
echo "VULN_COMMIT=$VULN_RESOLVED"
echo "FIXED_COMMIT=$FIXED_RESOLVED"

# Verify the patch presence.
echo "Verifying patch presence..."
cd "$REPO"
if git show "$FIXED_RESOLVED" --stat | grep -q "enrollment_router.go"; then
    echo "Fixed commit contains enrollment_router.go patch."
else
    echo "ERROR: fixed commit does not contain expected patch" >&2
    exit 1
fi

if git show "$VULN_RESOLVED" --stat | grep -q "enrollment_router.go"; then
    echo "ERROR: vulnerable commit appears to contain the fix" >&2
    exit 1
else
    echo "Vulnerable commit does not contain the expected patch."
fi

# Copy the repro test file into the repo at runtime.
REPRO_TEST_SRC="$REPRO_DIR/cve_2026_58165_repro_test.go"
if [[ ! -f "$REPRO_TEST_SRC" ]]; then
    echo "ERROR: repro test file missing: $REPRO_TEST_SRC" >&2
    exit 1
fi

run_repro() {
    local commit="$1"
    local label="$2"
    local result_file="$REPRO_DIR/${label}_result.json"
    local test_log="$LOGS/${label}_test.log"

    echo ""
    echo "=== Running $label ($commit) ==="
    cd "$REPO"
    git checkout -f "$commit"
    cp -f "$REPRO_TEST_SRC" "$REPO/tests/cve_2026_58165_repro_test.go"

    export PRUVA_CVE_RESULT="$result_file"
    echo "Running go test..."
    if ! timeout 600 go test -tags apitests -run Test_CVE202658165_AdminEnrollmentEscalation ./tests/... > "$test_log" 2>&1; then
        echo "WARNING: $label test exited non-zero; inspecting result file"
    fi

    echo "Result file:"
    cat "$result_file" || echo "(no result file)"

    # Clean up the copied test file so it does not pollute other commits.
    rm -f "$REPO/tests/cve_2026_58165_repro_test.go"
}

run_repro "$VULN_RESOLVED" "vulnerable"
run_repro "$FIXED_RESOLVED" "fixed"

# Compare results.
VULN_POSSIBLE="$(jq -r '.vulnerable // false' "$REPRO_DIR/vulnerable_result.json")"
FIXED_BLOCKED="$(jq -r '.fixed // false' "$REPRO_DIR/fixed_result.json")"

VULN_STATUS="$(jq -r '.create_status_code // 0' "$REPRO_DIR/vulnerable_result.json")"
FIXED_STATUS="$(jq -r '.create_status_code // 0' "$REPRO_DIR/fixed_result.json")"

echo ""
echo "=== Summary ==="
echo "Vulnerable commit create-status: $VULN_STATUS"
echo "Fixed commit create-status: $FIXED_STATUS"

if [[ "$VULN_POSSIBLE" == "true" && "$FIXED_BLOCKED" == "true" ]]; then
    echo "CONFIRMED: privilege escalation possible on vulnerable commit and blocked on fixed commit."
    CLAIM_OUTCOME="confirmed"
    REPRO_RESULT="confirmed"
    NOTES="Privilege escalation via enrollment management confirmed."
else
    echo "ERROR: expected vulnerable=true and fixed=true, got vulnerable=$VULN_POSSIBLE fixed=$FIXED_BLOCKED" >&2
    CLAIM_OUTCOME="unknown"
    REPRO_RESULT="inconclusive"
    NOTES="Could not confirm both vulnerable and fixed behavior."
fi

# Write runtime manifest.
RUNTIME_MANIFEST="$REPRO_DIR/runtime_manifest.json"
jq -n \
  --arg entrypoint_kind "api_remote" \
  --arg entrypoint_detail "OpenZiti controller management API /enrollments endpoint used by a non-admin identity to create an OTT enrollment for an admin identity" \
  --argjson service_started true \
  --argjson healthcheck_passed true \
  --argjson target_path_reached true \
  --argjson runtime_stack '["openziti-controller","go-test-harness"]' \
  --argjson proof_artifacts '["repro/vulnerable_result.json","repro/fixed_result.json","logs/reproduction_steps.log","logs/vulnerable_test.log","logs/fixed_test.log"]' \
  --arg notes "$NOTES" \
  '{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}' > "$RUNTIME_MANIFEST"

if [[ "$REPRO_RESULT" == "confirmed" ]]; then
    exit 0
else
    exit 1
fi
