<?php
/**
 * Deterministic PHP runtime blocking for user-written snippets.
 *
 * @package CodeSnippet
 */

namespace CodeSnippet;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

final class SnippetThreatScanner {

	/**
	 * Patterns blocked at PHP snippet runtime (silent no-op).
	 */
	public static function isRuntimeBlocked( string $code ): bool {
		return self::getRuntimeBlockReason( $code ) !== null;
	}

	/**
	 * Human-readable reason when runtime execution is blocked.
	 */
	public static function getRuntimeBlockReason( string $code ): ?string {
		$code = trim( $code );
		if ( $code === '' ) {
			return null;
		}

		$blocked = [
			'/\b(exit|die)\s*\(/i'                    => __( 'exit() and die() terminate the request and can blank the site.', 'wp-powersuite' ),
			'/\beval\s*\(/i'                          => __( 'eval() is not allowed in snippets.', 'wp-powersuite' ),
			'/dns_get_record/i'                       => __( 'dns_get_record() is blocked in snippets.', 'wp-powersuite' ),
			'/\b(?:shell_exec|passthru|proc_open|popen|system)\s*\(/i' => __( 'Operating-system command execution is not allowed.', 'wp-powersuite' ),
			'/\bexec\s*\(/i'                          => __( 'exec() is not allowed in snippets.', 'wp-powersuite' ),
			'/`[^`]*`/'                               => __( 'Backtick shell execution is not allowed.', 'wp-powersuite' ),
			'/\b(?:assert|create_function)\s*\(/i'    => __( 'assert() and create_function() can execute arbitrary code.', 'wp-powersuite' ),
			'/\b(?:call_user_func|call_user_func_array)\s*\(/i' => __( 'Dynamic function invocation (call_user_func) is not allowed.', 'wp-powersuite' ),
			'/\b(?:file_put_contents|fopen|file_get_contents)\s*\(/i' => __( 'Direct filesystem access from a snippet is not allowed.', 'wp-powersuite' ),
			'/\b(?:include_once|require_once|include|require)\b/i' => __( 'Including or requiring files is not allowed in snippets.', 'wp-powersuite' ),
			'/\bReflectionFunction\b/i'                => __( 'ReflectionFunction is not allowed in snippets.', 'wp-powersuite' ),
			'/preg_replace\s*\(\s*[\'"][^\'"]*\/e[\'"]/i' => __( 'preg_replace() with the /e modifier can execute arbitrary code.', 'wp-powersuite' ),
		];

		foreach ( $blocked as $pattern => $message ) {
			if ( preg_match( $pattern, $code ) ) {
				return $message;
			}
		}

		if ( preg_match_all( '/(base64_decode|error_reporting|ini_set)\s*\(/i', $code, $matches ) ) {
			if ( count( $matches[0] ) > 5 ) {
				return __( 'Excessive obfuscation or environment manipulation detected.', 'wp-powersuite' );
			}
		}

		$disallowed = apply_filters( 'wpps_code_snippet_disallowed_php', [] );
		foreach ( (array) $disallowed as $pattern ) {
			if ( is_string( $pattern ) && $pattern !== '' && preg_match( '#' . $pattern . '#i', $code ) ) {
				return __( 'This snippet uses a disallowed PHP pattern.', 'wp-powersuite' );
			}
		}

		return null;
	}
}
