<?php

declare(strict_types=1);

namespace ShieldX\Security;

defined('ABSPATH') || exit;

final class VirtualPatchVersionMatcher
{
    public static function matches(string $version, string $constraint): bool
    {
        $version = trim($version);
        $constraint = trim($constraint);
        if ($version === '' || $constraint === '' || !self::isValidConstraint($constraint)) {
            return false;
        }

        foreach (preg_split('/\s*\|\|\s*/', $constraint) ?: [] as $alternative) {
            $matches = true;
            foreach (preg_split('/\s*,\s*/', trim($alternative)) ?: [] as $clause) {
                if (preg_match('/^(<=|>=|<|>|=)?\s*([0-9][0-9A-Za-z._-]*)$/', trim($clause), $parts) !== 1) {
                    $matches = false;
                    break;
                }
                $operator = $parts[1] !== '' ? $parts[1] : '=';
                if (!version_compare($version, $parts[2], $operator)) {
                    $matches = false;
                    break;
                }
            }
            if ($matches) {
                return true;
            }
        }

        return false;
    }

    public static function isValidConstraint(string $constraint): bool
    {
        $constraint = trim($constraint);
        if ($constraint === '' || strlen($constraint) > 120) {
            return false;
        }

        foreach (preg_split('/\s*\|\|\s*/', $constraint) ?: [] as $alternative) {
            $clauses = preg_split('/\s*,\s*/', trim($alternative)) ?: [];
            if ($clauses === []) {
                return false;
            }
            foreach ($clauses as $clause) {
                if (preg_match('/^(<=|>=|<|>|=)?\s*[0-9][0-9A-Za-z._-]*$/', trim($clause)) !== 1) {
                    return false;
                }
            }
        }

        return true;
    }
}
