<?php

namespace WPSN\Modules\BulkTable\Admin;

defined('ABSPATH') || exit;

/**
 * Utility for staging → production URL/path rewrites.
 *
 * We keep it intentionally simple and safe:
 *  - only prefix replacements
 *  - supports URL-level rules (https://staging.tld => https://prod.tld)
 *  - supports path-level rules (/staging/ => /)
 */
final class PermalinkRewrite
{
    /**
     * Parse rewrite rules from a textarea.
     *
     * Supported formats (one rule per line):
     *  - FROM => TO
     *  - FROM -> TO
     * Lines starting with # are ignored.
     *
     * @return array<int,array{from:string,to:string,kind:string}>
     */
    public static function parseRules(string $raw): array
    {
        $raw = (string) $raw;
        if (trim($raw) === '') {
            return [];
        }

        $lines = preg_split('/\r\n|\r|\n/', $raw);
        if (!is_array($lines)) {
            return [];
        }

        $rules = [];
        foreach ($lines as $line) {
            $line = trim((string) $line);
            if ($line === '' || str_starts_with($line, '#')) {
                continue;
            }

            $from = '';
            $to = '';

            if (strpos($line, '=>') !== false) {
                [$from, $to] = array_map('trim', explode('=>', $line, 2));
            } elseif (strpos($line, '->') !== false) {
                [$from, $to] = array_map('trim', explode('->', $line, 2));
            } else {
                continue;
            }

            $from = trim($from, " \t\n\r\0\x0B\"'");
            $to = trim($to, " \t\n\r\0\x0B\"'");

            if ($from === '') {
                continue;
            }

            $kind = (strpos($from, '://') !== false) ? 'url' : 'path';

            $rules[] = [
                'from' => $from,
                'to' => $to,
                'kind' => $kind,
            ];
        }

        return $rules;
    }

    /**
     * Rewrite a raw URL/permalink into a local path ("/foo/bar/") by applying rules.
     *
     * @param array<int,array{from:string,to:string,kind:string}> $rules
     */
    public static function rewritePathFromUrl(string $rawUrl, array $rules): string
    {
        $rawUrl = trim((string) $rawUrl);
        if ($rawUrl === '') {
            return '';
        }

        // 1) Apply URL-level prefix rules to the full string.
        if (!empty($rules)) {
            foreach ($rules as $rule) {
                if (!is_array($rule)) {
                    continue;
                }
                if (($rule['kind'] ?? '') !== 'url') {
                    continue;
                }
                $from = (string) ($rule['from'] ?? '');
                $to = (string) ($rule['to'] ?? '');
                if ($from === '') {
                    continue;
                }
                if (str_starts_with($rawUrl, $from)) {
                    $rawUrl = $to . substr($rawUrl, strlen($from));
                }
            }
        }

        $path = (string) (parse_url($rawUrl, PHP_URL_PATH) ?? '');
        $path = '/' . ltrim($path, '/');

        // 2) Apply path-level prefix rules.
        if (!empty($rules)) {
            foreach ($rules as $rule) {
                if (!is_array($rule)) {
                    continue;
                }
                if (($rule['kind'] ?? '') !== 'path') {
                    continue;
                }

                $from = (string) ($rule['from'] ?? '');
                $to = (string) ($rule['to'] ?? '');

                if ($from === '') {
                    continue;
                }

                // Normalize.
                if (!str_starts_with($from, '/')) {
                    $from = '/' . ltrim($from, '/');
                }
                if ($to === '') {
                    $to = '/';
                }
                if (!str_starts_with($to, '/')) {
                    $to = '/' . ltrim($to, '/');
                }

                $path = self::replacePrefix($path, $from, $to);
            }
        }

        // Normalize multiple slashes.
        $path = preg_replace('#/+#', '/', $path) ?? $path;
        if ($path === '') {
            $path = '/';
        }

        return $path;
    }

    private static function replacePrefix(string $haystack, string $from, string $to): string
    {
        if ($from === '') {
            return $haystack;
        }

        if (str_starts_with($haystack, $from)) {
            $rest = substr($haystack, strlen($from));
            if ($to === '/') {
                return '/' . ltrim($rest, '/');
            }
            return rtrim($to, '/') . '/' . ltrim($rest, '/');
        }

        return $haystack;
    }
}
