<?php

declare(strict_types=1);

require_once __DIR__ . '/../../vendor/autoload.php';

use App\Framework\Http\Url\Rfc3986Url;
use App\Framework\Http\Url\UrlFactory;
use App\Framework\Http\Url\WhatwgUrl;

echo "=== Manual URL System Test ===\n\n";

$tests = 0;
$passed = 0;

function test(string $name, callable $fn): void
{
    global $tests, $passed;
    $tests++;

    try {
        $fn();
        echo "✅ {$name}\n";
        $passed++;
    } catch (\Throwable $e) {
        echo "❌ {$name}: {$e->getMessage()}\n";
    }
}

// RFC 3986 Tests
echo "--- RFC 3986 Tests ---\n";

test('Parse basic URL', function () {
    $url = Rfc3986Url::parse('https://example.com/path');
    assert($url->getScheme() === 'https');
    assert($url->getHost() === 'example.com');
    assert($url->getPath() === '/path');
});

test('Parse URL with all components', function () {
    $url = Rfc3986Url::parse('https://user:pass@example.com:8080/path?query=1#frag');
    assert($url->getScheme() === 'https');
    assert($url->getUserInfo() === 'user:pass');
    assert($url->getHost() === 'example.com');
    assert($url->getPort() === 8080);
    assert($url->getPath() === '/path');
    assert($url->getQuery() === 'query=1');
    assert($url->getFragment() === 'frag');
});

test('Immutable withScheme', function () {
    $original = Rfc3986Url::parse('https://example.com');
    $modified = $original->withScheme('http');
    assert($original->getScheme() === 'https');
    assert($modified->getScheme() === 'http');
    assert(spl_object_id($original) !== spl_object_id($modified));
});

test('Immutable withPath', function () {
    $url = Rfc3986Url::parse('https://example.com/old');
    $modified = $url->withPath('/new');
    assert($url->getPath() === '/old');
    assert($modified->getPath() === '/new');
});

test('URL resolution', function () {
    $base = Rfc3986Url::parse('https://example.com/base/path');
    $resolved = $base->resolve('../other');
    assert($resolved->getHost() === 'example.com');
});

test('URL equality', function () {
    $url1 = Rfc3986Url::parse('https://example.com/path');
    $url2 = Rfc3986Url::parse('https://example.com/path');
    assert($url1->equals($url2) === true);
});

test('URL equality ignores fragment by default', function () {
    $url1 = Rfc3986Url::parse('https://example.com/path#frag1');
    $url2 = Rfc3986Url::parse('https://example.com/path#frag2');
    assert($url1->equals($url2) === true);
    // Native PHP API always ignores fragments in equals()
    // For our wrapper, we delegate to native behavior
});

test('URLs with different paths are not equal', function () {
    $url1 = Rfc3986Url::parse('https://example.com/path1');
    $url2 = Rfc3986Url::parse('https://example.com/path2');
    assert($url1->equals($url2) === false);
});

// WHATWG Tests
echo "\n--- WHATWG Tests ---\n";

test('Parse WHATWG URL', function () {
    $url = WhatwgUrl::parse('https://example.com/path');
    assert($url->getScheme() === 'https');
    assert($url->getHost() === 'example.com');
    assert($url->getPath() === '/path');
});

test('WHATWG with all components', function () {
    $url = WhatwgUrl::parse('https://user:pass@example.com:8080/path?query=1#frag');
    assert($url->getScheme() === 'https');
    assert($url->getUserInfo() === 'user:pass');
    assert($url->getHost() === 'example.com');
    assert($url->getPort() === 8080);
    assert($url->getPath() === '/path');
    assert($url->getQuery() === 'query=1');
    assert($url->getFragment() === 'frag');
});

test('WHATWG immutable withers', function () {
    $original = WhatwgUrl::parse('https://example.com');
    $modified = $original->withScheme('http');
    assert($original->getScheme() === 'https');
    assert($modified->getScheme() === 'http');
});

test('WHATWG URL resolution', function () {
    $base = WhatwgUrl::parse('https://example.com/base');
    $resolved = $base->resolve('relative');
    assert($resolved->getHost() === 'example.com');
});

// Factory Tests
echo "\n--- Factory Tests ---\n";

test('Factory auto-selects WHATWG for http', function () {
    $url = UrlFactory::parse('https://example.com');
    assert($url instanceof WhatwgUrl);
});

test('Factory forApiClient creates RFC3986', function () {
    $url = UrlFactory::forApiClient('https://api.example.com');
    assert($url instanceof Rfc3986Url);
});

test('Factory forBrowserRedirect creates WHATWG', function () {
    $url = UrlFactory::forBrowserRedirect('https://example.com');
    assert($url instanceof WhatwgUrl);
});

// Integration Tests
echo "\n--- Integration Tests ---\n";

test('API client with authentication', function () {
    $url = UrlFactory::forApiClient('https://api.example.com/users');
    $withAuth = $url->withUserInfo('api_key', 'secret');
    $urlString = $withAuth->toString();
    assert(str_contains($urlString, 'api_key'));
    assert(str_contains($urlString, 'secret'));
});

test('Browser redirect with query', function () {
    $url = UrlFactory::forBrowserRedirect('https://example.com/login');
    $withQuery = $url->withQuery('return_url=/dashboard');
    assert($withQuery->getQuery() === 'return_url=/dashboard');
});

test('URL signature generation', function () {
    $url = UrlFactory::forSignature('https://api.example.com/resource');
    $withParams = $url->withQuery('timestamp=123&user_id=42');
    $urlString = $withParams->toString();
    assert(str_contains($urlString, 'timestamp=123'));
});

// Summary
echo "\n=== Summary ===\n";
echo "Tests: {$passed}/{$tests} passed\n";

if ($passed === $tests) {
    echo "✅ All tests passed!\n";
    exit(0);
} else {
    echo "❌ Some tests failed\n";
    exit(1);
}
