<?php

namespace MintyPHP\Tests\Module\Bookmarks\Support;

use MintyPHP\Module\Bookmarks\Support\BookmarkUrlNormalizer;
use PHPUnit\Framework\TestCase;

class BookmarkUrlNormalizerTest extends TestCase
{
    public function testCanonicalizeRelativeNormalizesPathAndQueryOrder(): void
    {
        $actual = BookmarkUrlNormalizer::canonicalizeRelative('/admin//users/?b=2&a=1');

        $this->assertSame('admin/users?a=1&b=2', $actual);
    }

    public function testCanonicalizeRelativeSortsMultiValueQueryKeys(): void
    {
        $actual = BookmarkUrlNormalizer::canonicalizeRelative('admin/users?roles=2&roles=1&search=max');

        $this->assertSame('admin/users?roles=1&roles=2&search=max', $actual);
    }

    public function testCanonicalizeRelativeRejectsAbsoluteUrl(): void
    {
        $actual = BookmarkUrlNormalizer::canonicalizeRelative('https://example.com/admin/users');

        $this->assertSame('', $actual);
    }

    public function testCanonicalizeRelativeRemovesFragment(): void
    {
        $actual = BookmarkUrlNormalizer::canonicalizeRelative('admin/users?a=1#section-2');

        $this->assertSame('admin/users?a=1', $actual);
    }

    public function testCanonicalizeRequestUriStripsLocaleBaseAndSortsQuery(): void
    {
        $actual = BookmarkUrlNormalizer::canonicalizeRequestUri('/de/admin/users?b=2&a=1', '/de/');

        $this->assertSame('admin/users?a=1&b=2', $actual);
    }

    public function testCanonicalizeRequestUriHandlesAppBaseAndLocale(): void
    {
        $actual = BookmarkUrlNormalizer::canonicalizeRequestUri('/core/de/address-book?tenants=b&tenants=a', '/core/de/');

        $this->assertSame('address-book?tenants=a&tenants=b', $actual);
    }

    public function testCanonicalizeRelativeRejectsDataUri(): void
    {
        $this->assertSame('', BookmarkUrlNormalizer::canonicalizeRelative('data:text/html,<script>alert(1)</script>'));
    }

    public function testCanonicalizeRelativeRejectsJavaScriptUri(): void
    {
        $this->assertSame('', BookmarkUrlNormalizer::canonicalizeRelative('javascript:alert(1)'));
        $this->assertSame('', BookmarkUrlNormalizer::canonicalizeRelative('JavaScript:alert(document.cookie)'));
    }

    public function testCanonicalizeRelativeRejectsFileUri(): void
    {
        $this->assertSame('', BookmarkUrlNormalizer::canonicalizeRelative('file:///etc/passwd'));
    }

    public function testCanonicalizeRelativeRejectsVbScriptUri(): void
    {
        $this->assertSame('', BookmarkUrlNormalizer::canonicalizeRelative('vbscript:MsgBox("xss")'));
    }

    public function testCanonicalizeRelativeRejectsNullBytes(): void
    {
        $this->assertSame('', BookmarkUrlNormalizer::canonicalizeRelative("admin/users\x00javascript:alert(1)"));
        $this->assertSame('', BookmarkUrlNormalizer::canonicalizeRelative("\x00"));
    }

    public function testCanonicalizeRelativeRejectsProtocolRelativeUrl(): void
    {
        $this->assertSame('', BookmarkUrlNormalizer::canonicalizeRelative('//evil.com/payload'));
    }

    public function testCanonicalizeRelativeHandlesDeepPathTraversal(): void
    {
        $this->assertSame('', BookmarkUrlNormalizer::canonicalizeRelative('admin/users/../../../../etc/passwd'));
    }
}
