<?php

use Beebmx\KirbySign\Signed;
use Carbon\Carbon;
use Kirby\Cms\App;
use Kirby\Toolkit\Str;

describe('validate query', function () {
    beforeEach(function () {
        App(options: ['beebmx.kirby-sign.key' => 'test-key']);
    });

    it('validates an url', function () {
        $expires = (new Signed)->url('/secret/page');
        $uri = Str::replace($expires, App::instance()->url(), '');

        App::destroy();
        App(options: ['beebmx.kirby-sign.key' => 'test-key'], uri: $uri);

        expect((new Signed)->isValid())
            ->toBeTrue();
    });

    it('validates an expire url', function () {
        $expires = (new Signed)->url('/secret/page', expiration: Carbon::now()->addHour());
        $uri = Str::replace($expires, App::instance()->url(), '');

        App::destroy();
        App(options: ['beebmx.kirby-sign.key' => 'test-key'], uri: $uri);

        expect((new Signed)->isValid())
            ->toBeTrue();
    });

    it('validates an expire url with parameters', function () {
        $expires = (new Signed)->url('/secret/page', ['foo' => 'bar'], expiration: Carbon::now()->addHour());
        $uri = Str::replace($expires, App::instance()->url(), '');

        App::destroy();
        App(options: ['beebmx.kirby-sign.key' => 'test-key'], uri: $uri);

        expect((new Signed)->isValid())
            ->toBeTrue();
    });

    it('expires for given Carbon time', function () {
        $expires = (new Signed)->url('/secret/page', expiration: Carbon::now()->addHour());
        $uri = Str::replace($expires, App::instance()->url(), '');

        App::destroy();
        Carbon::setTestNow(Carbon::now()->addHour()->addSecond());

        App(options: ['beebmx.kirby-sign.key' => 'test-key'], uri: $uri);

        expect((new Signed)->isValid())
            ->toBeFalse();
    });

    it('expires for given DateInterval', function () {
        $expires = (new Signed)->url('/secret/page', expiration: DateInterval::createFromDateString('1 hour'));
        $uri = Str::replace($expires, App::instance()->url(), '');

        App::destroy();
        Carbon::setTestNow(Carbon::now()->addHour()->addSecond());

        App(options: ['beebmx.kirby-sign.key' => 'test-key'], uri: $uri);

        expect((new Signed)->isValid())
            ->toBeFalse();
    });

    it('expires for given int expiration', function () {
        $expires = (new Signed)->url('/secret/page', expiration: 60);
        $uri = Str::replace($expires, App::instance()->url(), '');

        App::destroy();
        Carbon::setTestNow(Carbon::now()->addSeconds(61));

        App(options: ['beebmx.kirby-sign.key' => 'test-key'], uri: $uri);

        expect((new Signed)->isValid())
            ->toBeFalse();
    });
});

describe('validate params', function () {
    beforeEach(function () {
        App(options: ['beebmx.kirby-sign' => ['key' => 'test-key', 'format' => 'params']]);
    });

    it('validates an url', function () {
        $expires = (new Signed)->url('/secret/page');
        $uri = Str::replace($expires, App::instance()->url(), '');

        App::destroy();
        App(options: ['beebmx.kirby-sign' => ['key' => 'test-key', 'format' => 'params']], uri: $uri);

        expect((new Signed)->isValid())
            ->toBeTrue();
    });

    it('validates an expire url', function () {
        $expires = (new Signed)->url('/secret/page', expiration: Carbon::now()->addHour());
        $uri = Str::replace($expires, App::instance()->url(), '');

        App::destroy();
        App(options: ['beebmx.kirby-sign' => ['key' => 'test-key', 'format' => 'params']], uri: $uri);

        expect((new Signed)->isValid())
            ->toBeTrue();
    });

    it('validates an expire url with parameters', function () {
        $expires = (new Signed)->url('/secret/page', ['foo' => 'bar'], expiration: Carbon::now()->addHour());
        $uri = Str::replace($expires, App::instance()->url(), '');

        App::destroy();
        App(options: ['beebmx.kirby-sign' => ['key' => 'test-key', 'format' => 'params']], uri: $uri);

        expect((new Signed)->isValid())
            ->toBeTrue();
    });

    it('expires for given Carbon time', function () {
        $expires = (new Signed)->url('/secret/page', expiration: Carbon::now()->addHour());
        $uri = Str::replace($expires, App::instance()->url(), '');

        App::destroy();
        App(options: ['beebmx.kirby-sign' => ['key' => 'test-key', 'format' => 'params']], uri: $uri);
        Carbon::setTestNow(Carbon::now()->addHour()->addSecond());

        expect((new Signed)->isValid())
            ->toBeFalse();
    });

    it('expires for given DateInterval', function () {
        $expires = (new Signed)->url('/secret/page', expiration: DateInterval::createFromDateString('1 hour'));
        $uri = Str::replace($expires, App::instance()->url(), '');

        App::destroy();
        Carbon::setTestNow(Carbon::now()->addHour()->addSecond());

        App(options: ['beebmx.kirby-sign' => ['key' => 'test-key', 'format' => 'params']], uri: $uri);

        expect((new Signed)->isValid())
            ->toBeFalse();
    });

    it('expires for given int expiration', function () {
        $expires = (new Signed)->url('/secret/page', expiration: 60);
        $uri = Str::replace($expires, App::instance()->url(), '');

        App::destroy();
        Carbon::setTestNow(Carbon::now()->addSeconds(61));

        App(options: ['beebmx.kirby-sign' => ['key' => 'test-key', 'format' => 'params']], uri: $uri);

        expect((new Signed)->isValid())
            ->toBeFalse();
    });
});

describe('options', function () {
    it('can define a validation with different signature', function () {
        App(options: ['beebmx.kirby-sign' => ['key' => 'test-key', 'sign' => 'kirby']]);
        $expires = (new Signed)->url('/secret/page');
        $uri = Str::replace($expires, App::instance()->url(), '');

        App::destroy();
        App(options: ['beebmx.kirby-sign' => ['key' => 'test-key', 'sign' => 'kirby']], uri: $uri);

        expect((new Signed)->isValid())
            ->toBeTrue();
    });

    it('can set params insted of query', function () {
        App(options: ['beebmx.kirby-sign' => ['key' => 'test-key', 'format' => 'params']]);
        $expires = (new Signed)->url('/secret/page', ['foo' => 'bar', 'baz' => 'qux']);
        $uri = Str::replace($expires, App::instance()->url(), '');

        App::destroy();
        App(options: ['beebmx.kirby-sign' => ['key' => 'test-key', 'format' => 'params']], uri: $uri);

        expect((new Signed)->isValid())
            ->toBeTrue();
    });
});
