<?php

declare(strict_types=1);

use App\Framework\Http\Url\UrlSpec;
use App\Framework\Http\Url\UrlUseCase;

describe('UrlSpec', function () {
    describe('enum values', function () {
        it('has RFC3986 case', function () {
            expect(UrlSpec::RFC3986->value)->toBe('rfc3986');
        });

        it('has WHATWG case', function () {
            expect(UrlSpec::WHATWG->value)->toBe('whatwg');
        });
    });

    describe('use case mapping', function () {
        it('maps API_CLIENT to RFC3986', function () {
            $spec = UrlSpec::forUseCase(UrlUseCase::API_CLIENT);

            expect($spec)->toBe(UrlSpec::RFC3986);
        });

        it('maps CURL_REQUEST to RFC3986', function () {
            $spec = UrlSpec::forUseCase(UrlUseCase::CURL_REQUEST);

            expect($spec)->toBe(UrlSpec::RFC3986);
        });

        it('maps SIGNATURE_GENERATION to RFC3986', function () {
            $spec = UrlSpec::forUseCase(UrlUseCase::SIGNATURE_GENERATION);

            expect($spec)->toBe(UrlSpec::RFC3986);
        });

        it('maps CANONICAL_URL to RFC3986', function () {
            $spec = UrlSpec::forUseCase(UrlUseCase::CANONICAL_URL);

            expect($spec)->toBe(UrlSpec::RFC3986);
        });

        it('maps BROWSER_REDIRECT to WHATWG', function () {
            $spec = UrlSpec::forUseCase(UrlUseCase::BROWSER_REDIRECT);

            expect($spec)->toBe(UrlSpec::WHATWG);
        });

        it('maps DEEP_LINK to WHATWG', function () {
            $spec = UrlSpec::forUseCase(UrlUseCase::DEEP_LINK);

            expect($spec)->toBe(UrlSpec::WHATWG);
        });

        it('maps HTML_FORM_ACTION to WHATWG', function () {
            $spec = UrlSpec::forUseCase(UrlUseCase::HTML_FORM_ACTION);

            expect($spec)->toBe(UrlSpec::WHATWG);
        });

        it('maps CLIENT_SIDE_URL to WHATWG', function () {
            $spec = UrlSpec::forUseCase(UrlUseCase::CLIENT_SIDE_URL);

            expect($spec)->toBe(UrlSpec::WHATWG);
        });
    });

    describe('convenience methods', function () {
        it('checks if RFC3986', function () {
            expect(UrlSpec::RFC3986->isRfc3986())->toBeTrue();
            expect(UrlSpec::WHATWG->isRfc3986())->toBeFalse();
        });

        it('checks if WHATWG', function () {
            expect(UrlSpec::WHATWG->isWhatwg())->toBeTrue();
            expect(UrlSpec::RFC3986->isWhatwg())->toBeFalse();
        });
    });
});

describe('UrlUseCase', function () {
    describe('enum cases', function () {
        it('has all expected use cases', function () {
            $cases = UrlUseCase::cases();

            expect($cases)->toHaveCount(8);
            expect($cases)->toContain(UrlUseCase::API_CLIENT);
            expect($cases)->toContain(UrlUseCase::CURL_REQUEST);
            expect($cases)->toContain(UrlUseCase::SIGNATURE_GENERATION);
            expect($cases)->toContain(UrlUseCase::CANONICAL_URL);
            expect($cases)->toContain(UrlUseCase::BROWSER_REDIRECT);
            expect($cases)->toContain(UrlUseCase::DEEP_LINK);
            expect($cases)->toContain(UrlUseCase::HTML_FORM_ACTION);
            expect($cases)->toContain(UrlUseCase::CLIENT_SIDE_URL);
        });
    });

    describe('descriptions', function () {
        it('provides description for API_CLIENT', function () {
            $desc = UrlUseCase::API_CLIENT->description();

            expect($desc)->toContain('API');
            expect($desc)->toContain('REST');
        });

        it('provides description for BROWSER_REDIRECT', function () {
            $desc = UrlUseCase::BROWSER_REDIRECT->description();

            expect($desc)->toContain('Browser');
            expect($desc)->toContain('redirect');
        });

        it('provides description for SIGNATURE_GENERATION', function () {
            $desc = UrlUseCase::SIGNATURE_GENERATION->description();

            expect($desc)->toContain('signature');
            expect($desc)->toContain('OAuth');
        });

        it('provides descriptions for all use cases', function () {
            foreach (UrlUseCase::cases() as $useCase) {
                expect(strlen($useCase->description()))->toBeGreaterThan(0);
            }
        });
    });

    describe('recommended spec', function () {
        it('recommends RFC3986 for API_CLIENT', function () {
            $spec = UrlUseCase::API_CLIENT->recommendedSpec();

            expect($spec)->toBe(UrlSpec::RFC3986);
        });

        it('recommends WHATWG for BROWSER_REDIRECT', function () {
            $spec = UrlUseCase::BROWSER_REDIRECT->recommendedSpec();

            expect($spec)->toBe(UrlSpec::WHATWG);
        });

        it('provides recommendation for all use cases', function () {
            foreach (UrlUseCase::cases() as $useCase) {
                $spec = $useCase->recommendedSpec();

                expect($spec)->toBeInstanceOf(UrlSpec::class);
            }
        });
    });
});
