<?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\Services\User\ResetPassword\Request\Version2;

use Sso\WebserviceBundle\ErrorHandler\ErrorHandlerInterface;
use Sso\WebserviceBundle\Services\User\ResetPassword\Request\Version2\RequestParser;
use Sso\WebserviceBundle\Services\User\ResetPassword\RequestData\User as RequestDataUser;
use Sso\WebserviceBundle\Services\User\ResetPassword\RequestData\Factory as RequestDataFactory;
use JMS\Serializer\SerializerBuilder;
use InvalidArgumentException;
use JMS\Serializer\SerializerInterface;
use Symfony\Component\Validator\Validator\ValidatorInterface;
use Sso\WebserviceBundle\Api\Mapper\Index as AutoMapper;
use Sso\WebserviceBundle\Tests\Services\ServicesKernelTestCase;

/**
 * Class RequestParserTest
 *
 * @copyright  2016 Lifestyle Webconsulting GmbH
 * @link       http://www.life-style.de
 * @package Sso\WebserviceBundle\Tests\Services\User\Show\Request\Version2
 */
class RequestParserTest extends ServicesKernelTestCase
{
    private $validServiceToken = 'V2030cOhc6Vttcxs6r6bmtdlc8Z1ryTN1TQ16pjivEcprZhye9e17ba7508a4358f99c8ba52ded0f70RnZDhDyKMXLEWobXI2ZOrJ7mXjcPJJNk7wxoAw8WUTk0IMYa';
    private $validServiceName = 'MyService';
    private $validUserIdentifier = '5e211de5c4aa76564fc5e3657a7946aab3e2dbe60a773117568b3e67a2223a2c6878e5d25ee70588b19728f010417388f590128beced60402c7b8036b725ba71';
    private $validUsername = 'test@example.com';
    private $validServiceCountryCode = 'DE';

    public function testParseSuccess()
    {
        $identifier = $this->faker->uuid;
        $password = $this->faker->password;
        $newPassword = $this->faker->password;
        $authToken = hash('sha256', $this->faker->uuid);

        $serializer = SerializerBuilder::create()->build();

        $factory = new RequestDataFactory();
        $autoMapper = new AutoMapper();
        $errorHandler = $this->createMock(ErrorHandlerInterface::class);
        $errorHandler
            ->expects(self::never())
            ->method('addError');

        $validator = $this->createMock(ValidatorInterface::class);
        $validator
            ->method('validate')
            ->willReturn([]);

        $requestParser = new RequestParser(
            $serializer,
            $factory,
            $errorHandler,
            $validator,
            $autoMapper
        );

        /** @var RequestDataUser $model */
        $model = $requestParser->parse($this->generateSuccessXml($identifier, $password, $newPassword, $authToken));

        self::assertInstanceOf(RequestDataUser::class, $model);
        $this->assertEquals($password, $model->getPasswordData()->getCurrentPassword());
        $this->assertEquals($newPassword, $model->getPasswordData()->getNewPassword());
        $this->assertEquals($authToken, $model->getPasswordData()->getAuthToken());
        $this->assertEquals($identifier, $model->getIdentifier());
    }

    public function testParseErrorWrongParamsXml()
    {
        $serializer = SerializerBuilder::create()->build();

        $factory = new RequestDataFactory();
        $autoMapper = new AutoMapper();
        $errorHandler = $this->createMock(ErrorHandlerInterface::class);
        $errorHandler
            ->method('addError')
            ->willReturn(true);

        $requestParser = new RequestParser(
            $serializer,
            $factory,
            $errorHandler,
            $this->validator,
            $autoMapper
        );

        /** @var RequestDataUser $model */
        $model = $requestParser->parse($this->generateErrorXml());

        self::assertInstanceOf(RequestDataUser::class, $model);
    }

    /**
     * @expectedException InvalidArgumentException
     */
    public function testParseErrorSerializer()
    {
        $mockSerializer = $this->createMock(SerializerInterface::class);
        $mockSerializer->method('deserialize')->willReturn('42');

        $factory = new RequestDataFactory();
        $autoMapper = new AutoMapper();
        $errorHandler = $this->createMock(ErrorHandlerInterface::class);
        $errorHandler
            ->expects(self::never())
            ->method('addError');

        $validator = $this->createMock(ValidatorInterface::class);

        $requestParser = new RequestParser(
            $mockSerializer,
            $factory,
            $errorHandler,
            $validator,
            $autoMapper
        );

        /** @var RequestDataUser $model */
        $requestParser->parse('invalid xml');
    }

    /**
     * @param string $identifier email or username or guid
     * @param string $password
     * @param string $newPassword
     * @param string $authToken
     * @return string
     */
    private function generateSuccessXml($identifier, $password, $newPassword, $authToken)
    {
        return '<?xml version="1.0"?>
                <SsoRequest>
                    <Credentials>
                        <ServiceProvider>
                            <ServiceToken>' . $this->validServiceToken . '</ServiceToken>
                            <ServiceName>' . $this->validServiceName . '</ServiceName>
                        </ServiceProvider>
                        <ServiceTrigger>
                            <Username>' . $this->validUsername . '</Username>
                            <UserIdentifier>' . $this->validUserIdentifier . '</UserIdentifier>
                        </ServiceTrigger>
                        <ServiceCountry>
                            <Code>' . $this->validServiceCountryCode . '</Code>
                        </ServiceCountry>
                    </Credentials>
                    <User>
                        <ResetPassword>
                            <Key>
                                <UserType>
                                    <Identifier>'.$identifier.'</Identifier>
                                </UserType>
                            </Key>
                            <Value>
                                <UserType>
                                    <Password><![CDATA['.$password.']]></Password>
                                    <NewPassword><![CDATA['.$newPassword.']]></NewPassword>
                                    <AuthenticationToken><![CDATA['.$authToken.']]></AuthenticationToken>
                                </UserType>
                            </Value>
                        </ResetPassword>
                    </User>
                </SsoRequest>';
    }

    /**
     * @return string
     */
    private function generateErrorXml()
    {
        return '<?xml version="1.0"?>
                <SsoRequest>
                    <Credentials>
                        <ServiceProvider>
                            <ServiceToken>' . $this->validServiceToken . '</ServiceToken>
                            <ServiceName>' . $this->validServiceName . '</ServiceName>
                        </ServiceProvider>
                        <ServiceTrigger>
                            <Username>' . $this->validUsername . '</Username>
                            <UserIdentifier>' . $this->validUserIdentifier . '</UserIdentifier>
                        </ServiceTrigger>
                        <ServiceCountry>
                            <Code>' . $this->validServiceCountryCode . '</Code>
                        </ServiceCountry>
                    </Credentials>
                    <User>
                        <Show>
                            <Key>
                                <UserType>
                                    <IdentifierFail>ccc</IdentifierFail>
                                </UserType>
                            </Key>
                        </Show>
                    </User>
                </SsoRequest>';
    }
}
