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

namespace Sso\WebserviceBundle\Tests\Functional\Services\Tests\Version2;

use Sso\WebserviceBundle\Tests\Functional\Services\Helper\Credentials;
use Sso\WebserviceBundle\Tests\Functional\Services\Helper\Version2\FunctionalTestCase;
use Sso\WebserviceBundle\Tests\Functional\Services\Helper\Version2\Constants;
use Sso\WebserviceBundle\Tests\Functional\Services\Helper\Version2\Model\Application;
use Sso\WebserviceBundle\Tests\Functional\Services\Helper\Version2\Model\ApplicationAttribute;

/**
 * Class ApplicationAttributeAddTest
 *
 * @copyright  2017 Lifestyle Webconsulting GmbH
 * @link       http://www.life-style.de
 * @package Tests\Version2
 */
class ApplicationAttributeAddTest extends FunctionalTestCase
{
    public function testSuccess()
    {
        $application = $this->helperFactory->applicationAdd()->execute();
        $this->helperFactory->userPermissionAdd()->execute($application);

        $faker = \Faker\Factory::create();
        $applicationAttribute = new ApplicationAttribute(Constants::PREFIX . $faker->lastName);
        $applicationAttribute->setType('many');
        $applicationAttribute->setDisplayType('dropdown');
        $applicationAttribute->setAttributeOptions(['Label 1' => 1, 'Label 2' => 2]);

        $requestBody = $this->getRequest($application, $applicationAttribute);
        $response = $this->sendPostRequest('ApplicationAttribute', 'Add', $requestBody);

        static::assertEquals(200, $response->getStatusCode());

        $xml = $response->getContent();
        $xmlElement = $this->loadResponse($xml);

        $xmlElementExpected = $this->loadXmlDomElement(
            __DIR__ . '/xml/response-structure-success.xml',
            'SsoResponse'
        );

        static::assertEqualXMLStructure(
            $xmlElementExpected,
            $xmlElement,
            false,
            $this->fXml($requestBody, $xml, 'Xml structure check failed')
        );
    }

    public function testInvalidApplicationAttribute()
    {
        $application = $this->helperFactory->applicationAdd()->execute();
        $this->helperFactory->userPermissionAdd()->execute($application);

        $applicationAttribute = new ApplicationAttribute('');
        $applicationAttribute->setType('many');

        $requestBody = $this->getRequest($application, $applicationAttribute);
        $response = $this->sendPostRequest('ApplicationAttribute', 'Add', $requestBody);

        static::assertEquals(200, $response->getStatusCode());

        $xml = $response->getContent();
        $xmlElement = $this->loadResponse($xml);

        $xmlElementExpected = $this->loadXmlDomElement(
            __DIR__ . '/xml/response-structure-error.xml',
            'SsoResponse'
        );

        static::assertEqualXMLStructure(
            $xmlElementExpected,
            $xmlElement,
            false,
            $this->fXml($requestBody, $xml, 'Xml structure check failed')
        );

        // Value check
        $xmlSimple = simplexml_load_string($xml);
        static::assertEquals(
            Constants::STATUS_BAD_REQUEST,
            (string)$xmlSimple->Status,
            $this->fXml($requestBody, $xml, 'Global xml status code does not match!')
        );

        static::assertRegExp(
            Constants::REGEXP_DATE,
            (string)$xmlSimple->Date,
            $this->fXml($requestBody, $xml, 'Date format does not match!')
        );

        static::assertEquals(
            400,
            (string)$xmlSimple->Errors->Error->Code,
            $this->fXml($requestBody, $xml, 'Xml status code does not match!')
        );

        static::assertEquals(
            'External Error',
            (string)$xmlSimple->Errors->Error->Type,
            $this->fXml($requestBody, $xml, 'Error type does not match!')
        );
    }

    /**
     * @param Application $application
     * @param ApplicationAttribute $applicationAttribute
     * @return string
     */
    private function getRequest(Application $application, ApplicationAttribute $applicationAttribute)
    {
        $attributeOptions = [];
        foreach ($applicationAttribute->getAttributeOptions() ?? [] as $label => $value) {
            $attributeOptions[$label] = '<AttributeOption>' .
                '<Label>' . $this->cdata($label) . '</Label>' .
                '<Value>' . $this->cdata($value) . '</Value>' .
                '</AttributeOption>';
        }

        return '<?xml version="1.0" encoding="UTF-8"?>
<SsoRequest>' . (string)(new Credentials($this->configuration)) . '
    <ApplicationAttribute>
        <Add>
            <Key>
                <ApplicationType>
                    <Name>' . $this->cdata($application->getName()) . '</Name>
                </ApplicationType>
            </Key>
            <Value>
                <AttributeType>
                    <Name>' . $this->cdata($applicationAttribute->getName()) . '</Name>
                    <Type>' . $this->cdata($applicationAttribute->getType()) . '</Type>
                    <DisplayType>' . $this->cdata($applicationAttribute->getDisplayType()) . '</DisplayType>
                    ' . implode('', $attributeOptions) . '
                </AttributeType>
            </Value>
        </Add>
    </ApplicationAttribute>
</SsoRequest>';
    }
}
