<?php
declare(strict_types=1);

namespace KbMarkdownImporter\Frontend;

use KbMarkdownImporter\Plugin;

final class UrlBuilder
{
    private static string $embedBaseUrl = '';

    public static function beginEmbed(string $baseUrl): void
    {
        self::$embedBaseUrl = remove_query_arg(['kb_docs_route', 'kb_docs_product', 'kb_docs_version', 'kb_docs_page'], $baseUrl);
    }

    public static function endEmbed(): void
    {
        self::$embedBaseUrl = '';
    }

    public static function isEmbed(): bool
    {
        return '' !== self::$embedBaseUrl;
    }

    public static function docsIndex(): string
    {
        return self::route('index');
    }

    public static function product(string $productSlug): string
    {
        return self::route('product', $productSlug);
    }

    public static function version(string $productSlug, string $versionSlug): string
    {
        return self::route('version', $productSlug, $versionSlug);
    }

    public static function page(string $productSlug, string $versionSlug, string $pageSlug = ''): string
    {
        return self::route('page', $productSlug, $versionSlug, $pageSlug);
    }

    private static function route(string $route, string $productSlug = '', string $versionSlug = '', string $pageSlug = ''): string
    {
        if (self::isEmbed()) {
            $args = ['kb_docs_route' => $route];

            if ($productSlug) {
                $args['kb_docs_product'] = $productSlug;
            }

            if ($versionSlug) {
                $args['kb_docs_version'] = $versionSlug;
            }

            if ($pageSlug) {
                $args['kb_docs_page'] = $pageSlug;
            }

            return add_query_arg($args, self::$embedBaseUrl);
        }

        $base = trim((string) Plugin::settings()['docs_base_slug'], '/') ?: 'docs';

        if (self::supportsPrettyPermalinks()) {
            $parts = array_filter([$base, $productSlug, $versionSlug, $pageSlug], static fn (string $part): bool => '' !== $part);
            return home_url('/' . implode('/', array_map('rawurlencode', $parts)) . '/');
        }

        $args = ['kb_markdown_route' => $route];

        if ($productSlug) {
            $args['kb_product_slug'] = $productSlug;
        }

        if ($versionSlug) {
            $args['kb_version_slug'] = $versionSlug;
        }

        if ($pageSlug) {
            $args['kb_page_slug'] = $pageSlug;
        }

        return add_query_arg($args, home_url('/'));
    }

    private static function supportsPrettyPermalinks(): bool
    {
        return '' !== (string) get_option('permalink_structure', '');
    }

    public static function rewriteHtml(string $html): string
    {
        if (! self::isEmbed()) {
            return $html;
        }

        return preg_replace_callback('/href=(["\'])([^"\']+)\1/i', static function (array $matches): string {
            $url = html_entity_decode((string) $matches[2], ENT_QUOTES);
            $replacement = self::rewriteUrl($url);

            if (! $replacement) {
                return $matches[0];
            }

            return 'href=' . $matches[1] . esc_url($replacement) . $matches[1];
        }, $html) ?? $html;
    }

    private static function rewriteUrl(string $url): string
    {
        $parts = wp_parse_url($url);

        if (! is_array($parts)) {
            return '';
        }

        $query = [];
        if (! empty($parts['query'])) {
            wp_parse_str((string) $parts['query'], $query);
        }

        if (! empty($query['kb_markdown_route'])) {
            return self::route(
                sanitize_key((string) $query['kb_markdown_route']),
                sanitize_title((string) ($query['kb_product_slug'] ?? '')),
                sanitize_title((string) ($query['kb_version_slug'] ?? '')),
                sanitize_title((string) ($query['kb_page_slug'] ?? ''))
            );
        }

        $base = trim((string) Plugin::settings()['docs_base_slug'], '/') ?: 'docs';
        $path = trim((string) ($parts['path'] ?? ''), '/');

        if ($path === $base) {
            return self::docsIndex();
        }

        if (! str_starts_with($path . '/', $base . '/')) {
            return '';
        }

        $routeParts = array_values(array_filter(explode('/', substr($path, strlen($base))), static fn (string $part): bool => '' !== $part));

        if (1 === count($routeParts)) {
            return self::product(sanitize_title($routeParts[0]));
        }

        if (2 === count($routeParts)) {
            return self::version(sanitize_title($routeParts[0]), sanitize_title($routeParts[1]));
        }

        return self::page(
            sanitize_title($routeParts[0] ?? ''),
            sanitize_title($routeParts[1] ?? ''),
            sanitize_title(implode('/', array_slice($routeParts, 2)))
        );
    }
}
