<?php /** @noinspection PhpUnhandledExceptionInspection */

namespace App\Tests\Unit\Service\Network;

use App\Entity\Network\Network;
use App\Entity\Network\NetworkOrganization;
use App\Entity\Organization\Organization;
use App\Enum\Network\NetworkEnum;
use App\Service\Network\Utils as NetworkUtils;
use DateTime;
use Doctrine\Common\Collections\ArrayCollection;
use PHPUnit\Framework\TestCase;

class UtilsTest extends TestCase
{
    /**
     * @see Utils::isCMF()
     */
    public function testIsCmf():void
    {
        $networkUtils = $this
            ->getMockBuilder(NetworkUtils::class)
            ->setMethodsExcept(['isCMF'])
            ->getMock();

        $organization = $this->getMockBuilder(Organization::class)->getMock();

        $networkUtils
            ->expects(self::once())
            ->method('doesOrganizationBelongToTheNetwork')
            ->with($organization, NetworkEnum::CMF())
            ->willReturn(true);

        $result = $networkUtils->isCmf($organization);
        $this->assertTrue($result);
    }

    /**
     * @see Utils::isCMF()
     */
    public function testIsNotCmf():void
    {
        $networkUtils = $this
            ->getMockBuilder(NetworkUtils::class)
            ->setMethodsExcept(['isCMF'])
            ->getMock();

        $organization = $this->getMockBuilder(Organization::class)->getMock();
        $networkUtils
            ->expects(self::once())
            ->method('doesOrganizationBelongToTheNetwork')
            ->with($organization, NetworkEnum::CMF())
            ->willReturn(false);

        $result = $networkUtils->isCmf($organization);
        $this->assertFalse($result);
    }

    /**
     * @see Utils::isCMF()
     */
    public function testIsCmfAndActiveNow():void
    {
        $networkUtils = $this
            ->getMockBuilder(NetworkUtils::class)
            ->setMethodsExcept(['isCMFAndActiveNow'])
            ->getMock();

        $organization = $this->getMockBuilder(Organization::class)->getMock();
        $networkUtils
            ->expects(self::once())
            ->method('doesOrganizationBelongToTheNetwork')
            ->with($organization, NetworkEnum::CMF(), true)
            ->willReturn(false);

        $result = $networkUtils->isCMFAndActiveNow($organization);
        $this->assertFalse($result);
    }

    /**
     * @see Utils::doesOrganizationBelongToTheNetwork()
     */
    public function testDoesOrganizationBelongToTheNetwork():void
    {
        $networkUtils = $this
            ->getMockBuilder(NetworkUtils::class)
            ->setMethodsExcept(['doesOrganizationBelongToTheNetwork'])
            ->getMock();

        $organization = $this->getMockBuilder(Organization::class)->getMock();

        $network1 = $this->getMockBuilder(Network::class)->getMock();
        $network1->method('getId')->willReturn(NetworkEnum::CMF()->getValue());

        $networkOrganization1 = $this->getMockBuilder(NetworkOrganization::class)->getMock();
        $networkOrganization1->method('getNetwork')->willReturn($network1);

        $network2 = $this->getMockBuilder(Network::class)->getMock();
        $network2->method('getId')->willReturn(NetworkEnum::FFEC()->getValue());

        $networkOrganization2 = $this->getMockBuilder(NetworkOrganization::class)->getMock();
        $networkOrganization2->method('getNetwork')->willReturn($network2);

        $organization
            ->expects(self::once())
            ->method('getNetworkOrganizations')
            ->willReturn(new ArrayCollection([$networkOrganization1, $networkOrganization2]));

        $networkUtils->expects(self::never())->method('isNetworkOrganizationActiveNow');

        $result = $networkUtils->doesOrganizationBelongToTheNetwork($organization, NetworkEnum::FFEC());

        $this->assertTrue($result);
    }

    /**
     * @see Utils::doesOrganizationBelongToTheNetwork()
     */
    public function testDoesOrganizationBelongToTheNetworkAndActive():void
    {
        $networkUtils = $this
            ->getMockBuilder(NetworkUtils::class)
            ->setMethodsExcept(['doesOrganizationBelongToTheNetwork'])
            ->getMock();

        $organization = $this->getMockBuilder(Organization::class)->getMock();

        $network1 = $this->getMockBuilder(Network::class)->getMock();
        $network1->method('getId')->willReturn(NetworkEnum::CMF()->getValue());

        $networkOrganization1 = $this->getMockBuilder(NetworkOrganization::class)->getMock();
        $networkOrganization1->method('getNetwork')->willReturn($network1);

        $network2 = $this->getMockBuilder(Network::class)->getMock();
        $network2->method('getId')->willReturn(NetworkEnum::FFEC()->getValue());

        $networkOrganization2 = $this->getMockBuilder(NetworkOrganization::class)->getMock();
        $networkOrganization2->method('getNetwork')->willReturn($network2);

        $organization
            ->expects(self::once())
            ->method('getNetworkOrganizations')
            ->willReturn(new ArrayCollection([$networkOrganization1, $networkOrganization2]));

        $networkUtils->expects(self::once())->method('isNetworkOrganizationActiveNow')->with($networkOrganization2)->willReturn(true);

        $result = $networkUtils->doesOrganizationBelongToTheNetwork($organization, NetworkEnum::FFEC(), true);

        $this->assertTrue($result);
    }

    /**
     * @see Utils::doesOrganizationBelongToTheNetwork()
     */
    public function testDoesOrganizationBelongToTheNetworkFalse():void
    {
        $networkUtils = $this
            ->getMockBuilder(NetworkUtils::class)
            ->setMethodsExcept(['doesOrganizationBelongToTheNetwork'])
            ->getMock();

        $organization = $this->getMockBuilder(Organization::class)->getMock();

        $network1 = $this->getMockBuilder(Network::class)->getMock();
        $network1->method('getId')->willReturn(NetworkEnum::CMF()->getValue());

        $networkOrganization1 = $this->getMockBuilder(NetworkOrganization::class)->getMock();
        $networkOrganization1->method('getNetwork')->willReturn($network1);

        $network2 = $this->getMockBuilder(Network::class)->getMock();
        $network2->method('getId')->willReturn(NetworkEnum::FFEC()->getValue());

        $networkOrganization2 = $this->getMockBuilder(NetworkOrganization::class)->getMock();
        $networkOrganization2->method('getNetwork')->willReturn($network2);

        $organization
            ->expects(self::once())
            ->method('getNetworkOrganizations')
            ->willReturn(new ArrayCollection([$networkOrganization1, $networkOrganization2]));

        $networkUtils->expects(self::never())->method('isNetworkOrganizationActiveNow');

        $result = $networkUtils->doesOrganizationBelongToTheNetwork($organization, NetworkEnum::CFBF());

        $this->assertFalse($result);
    }

    /**
     * @see Utils::doesOrganizationBelongToTheNetwork()
     */
    public function testIsOrganizationActiveNow():void
    {
        $networkUtils = $this
            ->getMockBuilder(NetworkUtils::class)
            ->setMethodsExcept(['isNetworkOrganizationActiveNow'])
            ->getMock();

        $date1 = new DateTime('now');
        $date1->modify('-1 year');

        $date2 = new DateTime('now');
        $date2->modify('+1 year');

        $networkOrganization = $this->getMockBuilder(NetworkOrganization::class)->getMock();
        $networkOrganization
            ->expects(self::exactly(2))
            ->method('getStartDate')
            ->willReturn($date1);

        $networkOrganization
            ->expects(self::once())
            ->method('getEndDate')
            ->willReturn($date2);

        $this->assertTrue(
            $networkUtils->isNetworkOrganizationActiveNow($networkOrganization)
        );
    }

    /**
     * @see Utils::doesOrganizationBelongToTheNetwork()
     */
    public function testIsOrganizationActiveNowNotActive():void
    {
        $networkUtils = $this
            ->getMockBuilder(NetworkUtils::class)
            ->setMethodsExcept(['isNetworkOrganizationActiveNow'])
            ->getMock();

        $date1 = new DateTime('now');
        $date1->modify('-3 year');

        $date2 = new DateTime('now');
        $date2->modify('-1 year');

        $networkOrganization = $this->getMockBuilder(NetworkOrganization::class)->getMock();
        $networkOrganization
            ->expects(self::exactly(2))
            ->method('getStartDate')
            ->willReturn($date1);

        $networkOrganization
            ->expects(self::once())
            ->method('getEndDate')
            ->willReturn($date2);

        $this->assertFalse(
            $networkUtils->isNetworkOrganizationActiveNow($networkOrganization)
        );
    }
}
