<?php

namespace App\Tests\Unit\Service\Constraint;

use App\Service\Constraint\AbstractTimeConstraintUtils;
use App\Tests\Unit\TestToolsTrait;
use PHPUnit\Framework\TestCase;

class AbstractTimeConstraintsUtilsTest extends TestCase
{
    use TestToolsTrait;

    /**
     * @throws \ReflectionException
     * @see DateTimeConstraint::hasCustomPeriods()
     */
    public function testHasCustomPeriods(): void
    {
        $historical = ['dateStart' => '2020-09-01', 'dateEnd' => '2021-08-31'];

        $timeConstraintUtils = $this->getMockBuilder(AbstractTimeConstraintUtils::class)
            ->setConstructorArgs([])
            ->setMethodsExcept(['hasCustomPeriods'])
            ->getMock();

        $this->assertTrue($this->invokeMethod($timeConstraintUtils, 'hasCustomPeriods', [$historical]));
    }

    /**
     * @throws \ReflectionException
     * @see DateTimeConstraint::hasCustomPeriods()
     */
    public function testHasNotCustomPeriods(): void
    {
        $historical = ['dateStart' => null, 'dateEnd' => null];

        $timeConstraintUtils = $this->getMockBuilder(AbstractTimeConstraintUtils::class)
            ->setConstructorArgs([])
            ->setMethodsExcept(['hasCustomPeriods'])
            ->getMock();

        $this->assertFalse($this->invokeMethod($timeConstraintUtils, 'hasCustomPeriods', [$historical]));
    }

    /**
     * @see DateTimeConstraint::addConstraint()
     */
    public function testAddConstraint(): void
    {
        $originalConstraint = [
            'start' => [],
            'end' => []
        ];
        $presentConstraint = [
            'start' => [
                '2022-08-31' => 4
            ],
            'end' => [
                '2021-12-20' => 8,
                'NULL' => 0
            ]
        ];
        $pastConstraint = [
            'end' => [
                '2021-12-20' => 1
            ]
        ];
        $constraintAfterStartExpected = [
            'start' => [
                '2022-08-31' => [4]
            ],
            'end' => [
                '2021-12-20' => [8],
                'NULL' => [0]
            ]
        ];
        $constraintAfterEndExpected = [
            'start' => [
                '2022-08-31' => [4]
            ],
            'end' => [
                '2021-12-20' => [8, 1],
                'NULL' => [0]
            ]
        ];

        $timeConstraintUtils = $this->getMockBuilder(AbstractTimeConstraintUtils::class)
            ->setConstructorArgs([])
            ->setMethodsExcept(['addConstraint'])
            ->getMock();

        $this->assertEquals($constraintAfterStartExpected, $this->invokeMethod($timeConstraintUtils, 'addConstraint', [$originalConstraint, $presentConstraint]));
        $this->assertEquals($constraintAfterEndExpected, $this->invokeMethod($timeConstraintUtils, 'addConstraint', [$constraintAfterStartExpected, $pastConstraint]));
    }

    /**
     * @see AbstractTimeConstraintUtils::cleanConstraints()
     */
    public function testCleanConstraints(): void
    {
        $originalConstraint= [
            'start' => [
                '2022-08-31' => [5]
            ],
            'end' => [
                '2021-12-20' => [8, 1],
                'NULL' => [0]
            ]
        ];
        $constraintExpected= [
            'start' => [
                '2022-08-31' => [5]
            ],
            'end' => []
        ];

        $timeConstraintUtils = $this->getMockBuilder(AbstractTimeConstraintUtils::class)
            ->setConstructorArgs([])
            ->setMethodsExcept(['cleanConstraints'])
            ->getMock();

        $this->assertEquals($constraintExpected, $this->invokeMethod($timeConstraintUtils, 'cleanConstraints', [$originalConstraint]));
    }

    /**
     * @see AbstractTimeConstraintUtils::filterConstraint()
     */
    public function testFilterConstraint(): void
    {
        $originalStartConstraint= [
            'start' => [
                '2021-12-20' => [8, 1],
                '2022-01-01' => [5]
            ]
        ];
        $startConstraintExpected = [
            '2022-01-01' => [5]
        ];

        $timeConstraintUtils = $this->getMockBuilder(AbstractTimeConstraintUtils::class)
            ->setConstructorArgs([])
            ->setMethodsExcept(['filterConstraint'])
            ->getMock();

        $this->assertEquals(
            $startConstraintExpected,
            $this->invokeMethod($timeConstraintUtils, 'filterConstraint', [$originalStartConstraint, 'start'])
        );
    }

    /**
     * @see AbstractTimeConstraintUtils::clearNull()
     */
    public function testClearNull(): void
    {
        $originalEndConstraint= [
            'end' => [
                'NULL' => 0
            ]
        ];
        $endConstraintExpected = [];

        $timeConstraintUtils = $this->getMockBuilder(AbstractTimeConstraintUtils::class)
            ->setConstructorArgs([])
            ->setMethodsExcept(['clearNull'])
            ->getMock();

        $this->assertEquals($endConstraintExpected, $this->invokeMethod($timeConstraintUtils, 'clearNull', [$originalEndConstraint, 'end']));
    }
}
