<?php

namespace Buckhill\License\tests\units;

use Buckhill\License\Model\EncryptedLicense;
use Buckhill\License\Model\License;
use Buckhill\License\Model\Seal;
use mageekguy\atoum;
use Buckhill\License\LicenseManager as Manager;

class LicenseManager extends atoum
{
    public function testGenerateLicense()
    {
        $this->given($manager = new Manager())
            ->then
                ->object($license = $manager->generate($this->getValidLicenseInfo(), 'AES-256-CTR'))->isInstanceOf(License::class)
                ->object($loaded = $manager->load($this->getValidLicenseInfo()))->isInstanceOf(License::class)
                ->object($loaded_second = $manager->load($this->getValidLicenseInfo()))->isInstanceOf(License::class)

                // Two initialization vectors should be different even though actual model is the same
                ->boolean((0 === strcmp($loaded->getIV(), $loaded_second->getIV())))->isFalse()

            ;
    }


    public function testLoadLicense()
    {
        $this->given($manager = new Manager())
            ->then
                ->object($first = $manager->load($this->getValidLicenseInfo()))->isInstanceOf(License::class)
                ->object($second = $manager->load($this->getValidLicenseInfo()))->isInstanceOf(License::class)

                // Two initialization vectors should be different even though actual model is the same
                ->boolean((0 === strcmp($first->getIV(), $second->getIV())))->isFalse()

                // Check whether we get an instance of EncryptedLicense when we encrypt
                ->object($firstEnc = $first->encrypt(true))->isInstanceOf(EncryptedLicense::class)
                ->object($secondEnc = $second->encrypt(true))->isInstanceOf(EncryptedLicense::class)

                // Two encrypted payloads should be different
                ->boolean( 0 === strcmp($firstEnc->getEncryptedPayload(), $secondEnc->getEncryptedPayload()))->isFalse()
            ;
    }

    public function testSeal()
    {
        $this
            ->given($manager = new Manager())
            ->and($license = $manager->generate($this->getValidLicenseInfo()))

            ->then
                ->object($seal = $manager->seal($license, $this->getPrivateKeyValue(), '1234'))->isInstanceOf(Seal::class)
            ;
    }

    public function testUnseal()
    {
        $this
            ->given($manager = new Manager())
            ->and($license = $manager->generate($this->getValidLicenseInfo()))
            ->and($seal = $manager->seal($license, $this->getPrivateKeyValue(), '1234'))
            ->then
                ->object($unseal = $manager->unseal($seal->toString(), $this->getPublicKeyString()))->isInstanceOf(License::class)
            ;
    }


    /**
     * @return string
     */
    protected function getPrivateKeyValue()
    {
        return file_get_contents('.keys/testing.pem');
    }

    /**
     * @return mixed
     */
    protected function getPublicKeyString()
    {
        $key = @openssl_pkey_get_private(file_get_contents('.keys/testing.pem'), '1234');

        $details = @openssl_pkey_get_details($key);

        return $details['key'];
    }

    protected function getValidLicenseInfo()
    {
        return [
            'license' => [
                'id' => '6E6F5965A10A11E6A1670800274509D8',
                'startsAt' => 1481730870,
                'endsAt' => 1513266900,
                'gracePeriod' => '+7 days',
                'allowedNumberOfUsers' => 10,
                'numberOfProcessingServers' => 2
            ],

            /**
             * List of domains where license will function. If license is used at the domain that's not in this list,
             * the middleware checking the license will return an error, thus disabling the software
             */
            'domain' => ['localhost', '127.0.0.1'],


            /**
             * Information about two factor authentication (MFAStack functionality)
             */
            'twoFactor' => [
                'enabled' => false,
                'numberOfKeys' => [
                    'global' => 0,
                    'perPerson' => 0
                ]
            ],

            /**
             * Information about product that's being licensed
             */
            'product' => [
                'id' => 1,
                'title' => 'AuthStack IAM',
                'url' => 'https://www.buckhill.co.uk/products/authstack'
            ],

            /**
             * Information about contact person
             */
            'contact' => [
                'person' => 'Nikola B.',
                'email' => 'nikola@buckhill.co.uk'
            ],

            /**
             * Information about notification E-mail
             */
            'notificationEmail' => 'nikola@buckhill.co.uk',

            /**
             * Encryption information. This should be stored to permanent storage
             */
            'encryption' => [
                'alg' => 'AES-256-CTR',
                'key' => 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855',
                'iv' => '59BkphAozPiOfqPH'
            ]
        ];
    }
}