<?php

/**
 * Blocks dangerous PHP functions in generated plugin code.
 *
 * @package LolaCore\Builder\Safety\Rules
 * @license GPL-2.0-or-later
 */

declare(strict_types=1);

namespace LolaCore\Builder\Safety\Rules;

use LolaCore\Builder\Safety\SafetyContext;
use LolaCore\Builder\Safety\SafetyPhpHelper;
use LolaCore\Builder\Safety\SafetyRuleInterface;

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

/**
 * Subset of plugin-review PHPCS discouraged functions relevant to AI output.
 */
class ForbiddenFunctionsRule implements SafetyRuleInterface {

	/** @var array<int, string> */
	private const FORBIDDEN = array(
		'eval',
		'exec',
		'shell_exec',
		'passthru',
		'system',
		'proc_open',
		'popen',
		'create_function',
		'assert',
	);

	public function id(): string {
		return 'forbidden_functions';
	}

	/**
	 * @inheritDoc
	 */
	public function analyze( string $php, SafetyContext $context ): array {
		unset($context);

		$clean = SafetyPhpHelper::stripComments($php);
		$findings = array();

		foreach (self::FORBIDDEN as $function) {
			$pattern = '/\b' . preg_quote($function, '/') . '\s*\(/i';
			if (preg_match($pattern, $clean, $matches, PREG_OFFSET_CAPTURE) !== 1) {
				continue;
			}

			$matchText = (string) ( $matches[0][0] ?? $function );
			$offset    = (int) ( $matches[0][1] ?? 0 );
			$line      = $offset > 0
				? substr_count(substr($php, 0, $offset), "\n") + 1
				: SafetyPhpHelper::lineNumberForMatch($php, $matchText);

			$findings[] = array(
				'severity' => 'error',
				'code'     => $this->id(),
				'message'  => self::forbiddenFunctionMessage($function),
				'line'     => $line,
			);
		}

		return $findings;
	}

	private static function forbiddenFunctionMessage( string $function ): string {
		return match ($function) {
			'eval'            => __('eval() executes arbitrary PHP and is not allowed in generated plugins.', 'lolacore'),
			'exec'            => __('exec() runs shell commands and is not allowed in generated plugins.', 'lolacore'),
			'shell_exec'      => __('shell_exec() runs shell commands and is not allowed in generated plugins.', 'lolacore'),
			'passthru'        => __('passthru() runs shell commands and is not allowed in generated plugins.', 'lolacore'),
			'system'          => __('system() runs shell commands and is not allowed in generated plugins.', 'lolacore'),
			'proc_open'       => __('proc_open() runs shell commands and is not allowed in generated plugins.', 'lolacore'),
			'popen'           => __('popen() runs shell commands and is not allowed in generated plugins.', 'lolacore'),
			'create_function' => __('create_function() is deprecated and is not allowed in generated plugins.', 'lolacore'),
			'assert'          => __('assert() with string arguments can execute code and is not allowed in generated plugins.', 'lolacore'),
			default           => __('This function is not allowed in generated plugins.', 'lolacore'),
		};
	}
}
