<?php

/**
 * Lifestyle Webconsulting GmbH
 *
 * LICENSE: This Software is the property of Lifestyle Webconsulting GmbH (Aschaffenburg, Germany)
 * and is private by copyright law - it is NOT Freeware.
 *
 * Any unauthorized use of this software without a valid license
 * is a violation of the license agreement and will be prosecuted by
 * civil and criminal law.
 *
 * @copyright  2018 Lifestyle Webconsulting GmbH
 * @link       http://www.life-style.de
 */

namespace Sso\WebserviceBundle\Tests\Api\PasswordPolicy\User;

use PHPUnit\Framework\TestCase;
use Sso\WebserviceBundle\Database\Manager as DatabaseManager;
use Sso\WebserviceBundle\Entity\Webservice\Type\User;
use Sso\WebserviceBundle\Entity\Webservice\Type\PasswordPolicy;
use Sso\WebserviceBundle\Database\Webservice\User as DbUser;
use Sso\WebserviceBundle\Database\Webservice\Manager as WebserviceManager;
use Sso\WebserviceBundle\Database\Webservice\PasswordPolicy as DbPasswordPolicy;
use Sso\WebserviceBundle\Api\PasswordPolicy\User\Service;

/**
 * Class ServiceTest
 * @package Sso\WebserviceBundle\Tests\Api\PasswordPolicy\User
 */
class ServiceTest extends TestCase
{

    public function testService()
    {
        $passwordPolicy = new PasswordPolicy();
        $passwordPolicy
            ->setPolicyId('00000000-0000-0000-0000-000000000000')
            ->setRegEx('[^A-Za-z0-9]')
            ->setValidityDuration(60)
            ->setHistorySize(5)
            ->setChangeDelay(10)
            ->setEditDistance(4)
            ->setPolicyDescription('Test Policy');

        $mockDbPasswordPolicy = $this->makeMock(
            DbPasswordPolicy::class,
            [
                'getOne' => $passwordPolicy,
            ]
        );

        $mockUser = $this->makeMock(
            User::class,
            [
                'getPasswordPolicy' => '00000000-0000-0000-0000-000000000000',
                'isPasswordExpired' => true,
            ]
        );

        $mockDbUser = $this->makeMock(
            DbUser::class,
            [
                'getUserByGuid' => $mockUser,
                'saveUser' => true
            ]
        );

        $mockDbWebservice = $this->makeMock(
            WebserviceManager::class,
            [
                'user' => $mockDbUser,
                'passwordPolicy' => $mockDbPasswordPolicy,
            ]
        );

        $mockDbManager = $this->makeMock(
            DatabaseManager::class,
            [
                'webservice' => $mockDbWebservice
            ]
        );

        $service = new Service($mockDbManager);
        $checkResponse = $service->checkPasswordRenewRequired('1234');

        $this->assertEquals(true, $checkResponse->isForcePasswordReset());
        $this->assertGreaterThan(10, strlen($checkResponse->getResetPasswordToken()));
        $this->assertInstanceOf(\DateTime::class, $checkResponse->getResetPasswordTokenExpire());
    }

    /**
     * Helper function to ease the pain of creating 165382 mocks.... ;-)
     *
     * @param string $class
     * @param array $methodReturns
     * @return \PHPUnit_Framework_MockObject_MockObject
     */
    private function makeMock($class, $methodReturns)
    {
        $methods = [];
        foreach ($methodReturns as $method => $returnValue) {
            $methods[] = $method;
        }

        $mock = $this->getMockBuilder($class)
            ->disableOriginalConstructor()
            ->setMethods($methods)
            ->getMock();

        foreach ($methodReturns as $method => $returnValue) {
            $mock->expects($this->atLeastOnce())
                ->method($method)
                ->willReturn($returnValue);
        }

        return $mock;
    }
}
