<?php

declare(strict_types=1);

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

describe('UrlFactory', function () {
    describe('automatic spec selection', function () {
        it('selects WHATWG for http/https URLs', function () {
            $url = UrlFactory::parse('https://example.com/path');

            expect($url)->toBeInstanceOf(WhatwgUrl::class);
            expect($url->getSpec())->toBe(UrlSpec::WHATWG);
        });

        it('selects RFC3986 for non-http schemes', function () {
            $url = UrlFactory::parse('ftp://example.com/file');

            expect($url)->toBeInstanceOf(Rfc3986Url::class);
            expect($url->getSpec())->toBe(UrlSpec::RFC3986);
        });

        it('selects WHATWG for file:// URLs', function () {
            $url = UrlFactory::parse('file:///path/to/file');

            expect($url)->toBeInstanceOf(WhatwgUrl::class);
        });

        it('selects WHATWG for WebSocket URLs', function () {
            $url = UrlFactory::parse('ws://example.com/socket');

            expect($url)->toBeInstanceOf(WhatwgUrl::class);
        });
    });

    describe('use case factory methods', function () {
        it('creates RFC3986 URL for API client', function () {
            $url = UrlFactory::forApiClient('https://api.example.com/users');

            expect($url)->toBeInstanceOf(Rfc3986Url::class);
            expect($url->getHost())->toBe('api.example.com');
            expect($url->getPath())->toBe('/users');
        });

        it('creates RFC3986 URL for cURL request', function () {
            $url = UrlFactory::forCurlRequest('https://example.com/endpoint');

            expect($url)->toBeInstanceOf(Rfc3986Url::class);
        });

        it('creates RFC3986 URL for signature generation', function () {
            $url = UrlFactory::forSignature('https://api.example.com/resource');

            expect($url)->toBeInstanceOf(Rfc3986Url::class);
        });

        it('creates RFC3986 URL for canonical URLs', function () {
            $url = UrlFactory::forCanonical('https://example.com/page');

            expect($url)->toBeInstanceOf(Rfc3986Url::class);
        });

        it('creates WHATWG URL for browser redirect', function () {
            $url = UrlFactory::forBrowserRedirect('https://example.com/redirect');

            expect($url)->toBeInstanceOf(WhatwgUrl::class);
        });

        it('creates WHATWG URL for deep link', function () {
            $url = UrlFactory::forDeepLink('myapp://open/profile');

            expect($url)->toBeInstanceOf(WhatwgUrl::class);
        });

        it('creates WHATWG URL for form action', function () {
            $url = UrlFactory::forFormAction('https://example.com/submit');

            expect($url)->toBeInstanceOf(WhatwgUrl::class);
        });

        it('creates WHATWG URL for client-side JavaScript', function () {
            $url = UrlFactory::forClientSide('https://example.com/api/data');

            expect($url)->toBeInstanceOf(WhatwgUrl::class);
        });
    });

    describe('use case automatic selection', function () {
        it('creates RFC3986 for API_CLIENT use case', function () {
            $url = UrlFactory::forUseCase(
                UrlUseCase::API_CLIENT,
                'https://api.example.com/users'
            );

            expect($url)->toBeInstanceOf(Rfc3986Url::class);
        });

        it('creates RFC3986 for CURL_REQUEST use case', function () {
            $url = UrlFactory::forUseCase(
                UrlUseCase::CURL_REQUEST,
                'https://example.com/file'
            );

            expect($url)->toBeInstanceOf(Rfc3986Url::class);
        });

        it('creates RFC3986 for SIGNATURE_GENERATION use case', function () {
            $url = UrlFactory::forUseCase(
                UrlUseCase::SIGNATURE_GENERATION,
                'https://api.example.com/sign'
            );

            expect($url)->toBeInstanceOf(Rfc3986Url::class);
        });

        it('creates RFC3986 for CANONICAL_URL use case', function () {
            $url = UrlFactory::forUseCase(
                UrlUseCase::CANONICAL_URL,
                'https://example.com/page'
            );

            expect($url)->toBeInstanceOf(Rfc3986Url::class);
        });

        it('creates WHATWG for BROWSER_REDIRECT use case', function () {
            $url = UrlFactory::forUseCase(
                UrlUseCase::BROWSER_REDIRECT,
                'https://example.com/redirect'
            );

            expect($url)->toBeInstanceOf(WhatwgUrl::class);
        });

        it('creates WHATWG for DEEP_LINK use case', function () {
            $url = UrlFactory::forUseCase(
                UrlUseCase::DEEP_LINK,
                'myapp://open'
            );

            expect($url)->toBeInstanceOf(WhatwgUrl::class);
        });

        it('creates WHATWG for HTML_FORM_ACTION use case', function () {
            $url = UrlFactory::forUseCase(
                UrlUseCase::HTML_FORM_ACTION,
                'https://example.com/submit'
            );

            expect($url)->toBeInstanceOf(WhatwgUrl::class);
        });

        it('creates WHATWG for CLIENT_SIDE_URL use case', function () {
            $url = UrlFactory::forUseCase(
                UrlUseCase::CLIENT_SIDE_URL,
                'https://example.com/api'
            );

            expect($url)->toBeInstanceOf(WhatwgUrl::class);
        });
    });

    describe('spec conversion', function () {
        it('converts RFC3986 to WHATWG', function () {
            $rfc = UrlFactory::forApiClient('https://example.com/path');
            $whatwg = UrlFactory::convert($rfc, UrlSpec::WHATWG);

            expect($whatwg)->toBeInstanceOf(WhatwgUrl::class);
            expect($whatwg->getHost())->toBe('example.com');
            expect($whatwg->getPath())->toBe('/path');
        });

        it('converts WHATWG to RFC3986', function () {
            $whatwg = UrlFactory::forBrowserRedirect('https://example.com/path');
            $rfc = UrlFactory::convert($whatwg, UrlSpec::RFC3986);

            expect($rfc)->toBeInstanceOf(Rfc3986Url::class);
            expect($rfc->getHost())->toBe('example.com');
            expect($rfc->getPath())->toBe('/path');
        });

        it('returns same instance if already correct spec', function () {
            $rfc = UrlFactory::forApiClient('https://example.com');
            $converted = UrlFactory::convert($rfc, UrlSpec::RFC3986);

            expect($converted)->toBe($rfc);
        });
    });

    describe('integration scenarios', function () {
        it('creates API client URL with authentication', function () {
            $url = UrlFactory::forApiClient('https://api.example.com/users');
            $withAuth = $url->withUserInfo('api_key', 'secret');

            expect($withAuth->getUserInfo())->toBe('api_key:secret');
            expect($withAuth->toString())->toContain('api_key:secret');
        });

        it('creates redirect URL with query parameters', function () {
            $url = UrlFactory::forBrowserRedirect('https://example.com/login');
            $withParams = $url->withQuery('return_url=/dashboard&status=success');

            expect($withParams->getQuery())->toContain('return_url');
        });

        it('creates canonical URL without query and fragment', function () {
            $url = UrlFactory::forCanonical('https://example.com/page?utm=123#section');
            $canonical = $url->withQuery('')->withFragment('');

            expect($canonical->toString())->toBe('https://example.com/page');
        });

        it('creates signature-safe URL', function () {
            $url = UrlFactory::forSignature('https://api.example.com/resource');
            $withSig = $url->withQuery('timestamp=1234567890&signature=abc123');

            $urlString = $withSig->toString();

            expect($urlString)->toContain('timestamp=1234567890');
            expect($urlString)->toContain('signature=abc123');
        });

        it('creates deep link with custom data', function () {
            $url = UrlFactory::forDeepLink('myapp://open/profile');
            $withData = $url->withQuery('user_id=123&action=view');

            expect($withData->getScheme())->toBe('myapp');
            expect($withData->getQuery())->toContain('user_id=123');
        });
    });

    describe('real-world scenarios', function () {
        it('handles OAuth URL construction', function () {
            $authUrl = UrlFactory::forApiClient('https://oauth.example.com/authorize');
            $withParams = $authUrl->withQuery('client_id=123&redirect_uri=https://app.com&scope=read');

            expect($withParams->getQuery())->toContain('client_id=123');
            expect($withParams->getQuery())->toContain('redirect_uri');
        });

        it('handles REST API pagination', function () {
            $apiUrl = UrlFactory::forApiClient('https://api.example.com/users');
            $page2 = $apiUrl->withQuery('page=2&per_page=50');

            expect($page2->getQuery())->toBe('page=2&per_page=50');
        });

        it('handles mobile deep link with fallback', function () {
            $deepLink = UrlFactory::forDeepLink('myapp://open/article/123');
            $fallback = UrlFactory::forBrowserRedirect('https://example.com/article/123');

            expect($deepLink->getScheme())->toBe('myapp');
            expect($fallback->getScheme())->toBe('https');
        });

        it('handles form submission with CSRF token', function () {
            $formAction = UrlFactory::forFormAction('https://example.com/submit');
            $withToken = $formAction->withQuery('csrf_token=abc123');

            expect($withToken->getQuery())->toContain('csrf_token');
        });
    });
});
