<?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  2016 Lifestyle Webconsulting GmbH
 * @link       http://www.life-style.de
 */

namespace Sso\WebserviceBundle\Tests\Services\UserSearch\Advanced\Request\Version2;

use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Sso\WebserviceBundle\Api\ApiManagerInterface;
use JMS\Serializer\SerializerInterface;
use Sso\WebserviceBundle\Services\UserSearch\Advanced\Request\Version2 as Model;
use Sso\WebserviceBundle\Services\UserSearch\Advanced\Request\Version2\RequestParser;
use Sso\WebserviceBundle\ErrorHandler\ErrorHandlerInterface;
use Symfony\Component\Validator\Validator\ValidatorInterface;
use Sso\WebserviceBundle\Services\UserSearch\Advanced\RequestData\Factory as RequestFactory;
use Sso\WebserviceBundle\Services\UserSearch\Advanced\RequestData\UserSearch as RequestDTO;
use Sso\WebserviceBundle\Services\UserSearch\Advanced\RequestData\UserType;
use Sso\WebserviceBundle\Services\UserSearch\Advanced\RequestData\ApplicationType;
use Sso\WebserviceBundle\Services\UserSearch\Advanced\RequestData\AttributeType;
use Sso\WebserviceBundle\Services\UserSearch\Advanced\RequestData\RoleType;
use Sso\WebserviceBundle\Services\UserSearch\Advanced\RequestData\Filter;

/**
 * Class RequestParserTest
 *
 * @copyright  2016 Lifestyle Webconsulting GmbH
 * @link       http://www.life-style.de
 * @package Sso\WebserviceBundle\Tests\Services
 */
class RequestParserTest extends WebTestCase
{
    /**
     * @var SerializerInterface
     */
    private $serializer;

    /**
     * @var ApiManagerInterface
     */
    private $apiManager;

    protected function setUp()
    {
        parent::setUp();
        static::bootKernel();
        $this->apiManager = static::$kernel->getContainer()->get('service_api_manager');
        $this->serializer = $this->apiManager->serializer();
    }

    public function testParser()
    {
        $errorHandlerMock = $this->getMockBuilder(ErrorHandlerInterface::class)->getMock();
        $validatorMock = $this->getMockBuilder(ValidatorInterface::class)->getMock();
        $factory = new RequestFactory();
        $requestParser = new RequestParser($this->serializer, $factory, $errorHandlerMock, $validatorMock);
        $requestDTO = $requestParser->parse($this->getRequestBody());
        $this->assertInstanceOf(RequestDTO::class, $requestDTO);

        $this->assertEquals(0, $requestDTO->getOffset());
        $this->assertEquals(100, $requestDTO->getLimit());
        $this->assertEquals('createdAt', $requestDTO->getOrderBy());
        $this->assertEquals('ASC', $requestDTO->getOrderDir());
        $this->assertEquals(1, $requestDTO->getFullResponse());

        $filters = $requestDTO->getFilters()->toArray();
        $this->assertCount(4, $filters);


        // First filter
        /** @var  \Sso\WebserviceBundle\Services\UserSearch\Advanced\RequestData\Filter $filter */
        $filter = array_shift($filters);
        $this->assertEquals('EQUAL', $filter->getStrategy());
        $this->assertEquals('OR', $filter->getOperator());
        /** @var \Sso\WebserviceBundle\Services\UserSearch\Advanced\RequestData\UserType $userType */
        $userType = $filter->getUserType();
        $this->assertInstanceOf(UserType::class, $userType);
        $this->assertEquals(null, $userType->getOperator());
        $this->assertEquals('TestGuid', $userType->getGuid());
        $this->assertEquals('my@email.de', $userType->getEmail());
        $this->assertEquals('Username', $userType->getUsername());
        $this->assertEquals('Firstname', $userType->getFirstname());
        $this->assertEquals('Lastname', $userType->getLastname());
        $this->assertEquals(1, $userType->getActive());
        $this->assertEquals(1, $userType->getDeleted());
        $this->assertEquals(1, $userType->getMfaEnabled());
        $this->assertEquals(new \DateTime('1976-04-23T00:05:00+01:00'), $userType->getCreatedAt());


        // Secound filter
        $filter = array_shift($filters);
        $this->assertEquals('EQUAL', $filter->getStrategy());
        $this->assertEquals('AND', $filter->getOperator());

        /** @var \Sso\WebserviceBundle\Services\UserSearch\Advanced\RequestData\ApplicationType $applicationType */
        $applicationType = $filter->getApplicationType();
        $this->assertInstanceOf(ApplicationType::class, $applicationType);
        $this->assertEquals('ApplicationName', $applicationType->getName());
        $this->assertEquals(1, $applicationType->getActive());


        // Third filter
        $filter = array_shift($filters);
        $this->assertEquals('REGEX', $filter->getStrategy());
        $this->assertEquals('AND', $filter->getOperator());

        /** @var \Sso\WebserviceBundle\Services\UserSearch\Advanced\RequestData\ApplicationType $applicationType */
        $applicationType = $filter->getApplicationType();
        $this->assertInstanceOf(ApplicationType::class, $applicationType);
        $this->assertEquals('ApplicationName', $applicationType->getName());
        $this->assertEquals(1, $applicationType->getActive());

        /** @var \Sso\WebserviceBundle\Services\UserSearch\Advanced\RequestData\AttributeType $attributeType */
        $attributeType = $applicationType->getAttributeType();
        $this->assertInstanceOf(AttributeType::class, $attributeType);
        $this->assertEquals('AttributeName', $attributeType->getName());
        $this->assertEquals('AttributeValue', $attributeType->getValue());
        $this->assertEquals(1, $attributeType->getActive());

        /** @var \Sso\WebserviceBundle\Services\UserSearch\Advanced\RequestData\RoleType $roleType */
        $roleType = $applicationType->getRoleType();
        $this->assertInstanceOf(RoleType::class, $roleType);
        $this->assertEquals('MyRoleName', $roleType->getName());
        $this->assertEquals(1, $roleType->getActive());


        // Fourth filter (filters->filter)
        $filter = array_shift($filters);
        $this->assertEquals('EQUAL', $filter->getStrategy());
        $this->assertEquals('AND', $filter->getOperator());

        // Nested filters within fourth filter
        $nestedFilters = $filter->getFilters();
        $this->assertInstanceOf(ArrayCollection::class, $nestedFilters);
        $nestedFilters = $nestedFilters->toArray();

        // First nested filter
        $nestedFilter = array_shift($nestedFilters);
        $this->assertInstanceOf(Filter::class, $nestedFilter);

        // Second nested filter
        $nestedFilter = array_shift($nestedFilters);
    }

    /**
     * @return string
     */
    private function getRequestBody()
    {
        return '<?xml version="1.0"?>
                <SsoRequest>
                  <UserSearch>
                    <Advanced>
                      <Offset>0</Offset>
                      <Limit>100</Limit>
                      <OrderBy>createdAt</OrderBy>
                      <OrderDir>ASC</OrderDir>
                      <FullResponse>1</FullResponse>
                      <Filters>
                        <Filter>
                            <Strategy>EQUAL</Strategy>
                            <Operator>OR</Operator>
                            <UserType>
                                <Operator>AND</Operator>
                                <Guid>TestGuid</Guid>
                                <Email>my@email.de</Email>
                                <Username>Username</Username>
                                <Firstname>Firstname</Firstname>
                                <Lastname>Lastname</Lastname>
                                <Active>1</Active>
                                <Deleted>1</Deleted>
                                <MfaEnabled>1</MfaEnabled>
                                <CreatedAt>1976-04-23T00:05:00+01:00</CreatedAt>
                            </UserType>
                        </Filter>
                        <Filter>
                            <Strategy>EQUAL</Strategy>
                            <Operator>AND</Operator>
                            <ApplicationType>
                                <Operator>AND</Operator>
                                <Name>ApplicationName</Name>
                                <Active>1</Active>
                            </ApplicationType>
                        </Filter>
                        <Filter>
                          <Strategy>REGEX</Strategy>
                          <Operator>AND</Operator>
                          <ApplicationType>
                            <Operator>AND</Operator>
                            <Name>ApplicationName</Name>
                            <Active>1</Active>
                            <AttributeType>
                              <Operator>AND</Operator>
                              <Name>AttributeName</Name>
                              <Value>AttributeValue</Value>
                              <Active>1</Active>
                            </AttributeType>
                            <RoleType>
                              <Operator>AND</Operator>
                              <Name>MyRoleName</Name>
                              <Active>1</Active>
                            </RoleType>
                          </ApplicationType>
                        </Filter>
                        <Filter>
                          <Strategy>EQUAL</Strategy>
                          <Operator>AND</Operator>
                          <Filters>
                            <Filter>
                              <Strategy>EQUAL</Strategy>
                              <Operator>OR</Operator>
                              <UserType>
                                <Operator>AND/OR</Operator>
                                <Guid>TestGuid99</Guid>
                                <Email>my@email.de</Email>
                                <Username>Username</Username>
                                <Firstname>Firstname</Firstname>
                                <Lastname>Lastname</Lastname>
                                <Active>1</Active>
                                <Deleted>1</Deleted>
                                <MfaEnabled>1</MfaEnabled>
                                <CreatedAt>1976-04-23T00:05:00+01:00</CreatedAt>
                              </UserType>
                            </Filter>
                            <Filter>
                              <Strategy>EQUAL</Strategy>
                              <Operator>AND</Operator>
                              <ApplicationType>
                                <Operator>AND</Operator>
                                <Name>ApplicationName</Name>
                                <Active>1</Active>
                              </ApplicationType>
                            </Filter>
                          </Filters>
                        </Filter>
                      </Filters>
                    </Advanced>
                  </UserSearch>
                </SsoRequest>';
    }
}
