<?php

namespace WPSN\Modules\Redirects;

defined('ABSPATH') || exit;

/**
 * Helper for importing regex redirects from other plugins.
 *
 * The Redirects runtime matches only request paths (no query strings), so the
 * migration layer stays conservative and rejects patterns that are clearly
 * query-string specific or full-URL based.
 */
final class RedirectMigrationRegex
{
    /**
     * @return array{ok: bool, rule?: array<string,mixed>, reason?: string, message?: string, warnings?: array<int,string>, pattern?: string}
     */
    public static function buildRule(string $pattern, string $destination, int $statusCode, bool $enabled): array
    {
        $normalized = self::normalizeImportedPattern($pattern);
        if ($normalized === '') {
            return [
                'ok' => false,
                'reason' => 'missing_from',
                'message' => __('Regex pattern is empty.', 'wp-seo-next'),
                'pattern' => '',
            ];
        }

        if (self::looksLikeFullUrlRegex($normalized)) {
            return [
                'ok' => false,
                'reason' => 'full_url_regex',
                'message' => __('Regex rules that match a full URL are not imported automatically because WP SEO Next matches paths only.', 'wp-seo-next'),
                'pattern' => $normalized,
            ];
        }

        if (self::looksQuerySpecific($normalized)) {
            return [
                'ok' => false,
                'reason' => 'query_regex',
                'message' => __('Regex rules that depend on a query string are not imported automatically because WP SEO Next matches paths only.', 'wp-seo-next'),
                'pattern' => $normalized,
            ];
        }

        $destination = trim($destination);
        $validation = RedirectRegex::validateRule($normalized, $destination, $statusCode);
        if (!$validation['ok']) {
            return [
                'ok' => false,
                'reason' => 'regex_invalid',
                'message' => (string) $validation['message'],
                'warnings' => array_values(array_map('strval', $validation['warnings'] ?? [])),
                'pattern' => $normalized,
            ];
        }

        return [
            'ok' => true,
            'rule' => [
                'from_url' => RedirectRegex::normalizeStoredPattern($normalized),
                'to_url' => $destination !== '' ? $destination : null,
                'match_type' => 'regex',
                'status_code' => $statusCode,
                'enabled' => $enabled ? 1 : 0,
            ],
            'warnings' => array_values(array_map('strval', $validation['warnings'] ?? [])),
            'pattern' => $normalized,
        ];
    }

    public static function normalizeImportedPattern(string $pattern): string
    {
        $pattern = trim($pattern);
        if ($pattern === '') {
            return '';
        }

        if (self::looksDelimitedPattern($pattern)) {
            return $pattern;
        }

        if (strpos($pattern, '://') !== false) {
            return $pattern;
        }

        if (strpos($pattern, '^/') === 0) {
            return $pattern;
        }

        if ($pattern[0] === '^') {
            return '^/' . ltrim(substr($pattern, 1), '/');
        }

        if ($pattern[0] === '/') {
            return '^' . $pattern;
        }

        return '^/' . ltrim($pattern, '/');
    }

    public static function looksQuerySpecific(string $pattern): bool
    {
        return strpos($pattern, '\\?') !== false
            || strpos($pattern, '\\#') !== false
            || strpos($pattern, 'QUERY_STRING') !== false
            || strpos($pattern, 'query=') !== false;
    }

    public static function looksLikeFullUrlRegex(string $pattern): bool
    {
        return strpos($pattern, '://') !== false
            || strpos($pattern, '^https') === 0
            || strpos($pattern, '#^https') === 0
            || strpos($pattern, '~^https') === 0;
    }

    private static function looksDelimitedPattern(string $pattern): bool
    {
        if (strlen($pattern) < 3) {
            return false;
        }

        $delim = $pattern[0];
        if (ctype_alnum($delim) || $delim === '\\' || $delim === ' ') {
            return false;
        }

        $len = strlen($pattern);
        for ($i = $len - 1; $i > 0; $i--) {
            if ($pattern[$i] !== $delim) {
                continue;
            }

            if ($pattern[$i - 1] === '\\') {
                continue;
            }

            $mods = substr($pattern, $i + 1);
            if ($mods === '' || preg_match('/^[A-Za-z]*$/', $mods)) {
                return true;
            }
        }

        return false;
    }
}
