<?php

declare(strict_types=1);

/*
 * Chill is a software for social workers
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */

namespace Chill\PersonBundle\Tests\Entity\SocialWork;

use Chill\PersonBundle\Entity\SocialWork\SocialIssue;
use Doctrine\Common\Collections\ArrayCollection;
use PHPUnit\Framework\TestCase;

/**
 * @internal
 *
 * @coversNothing
 */
final class SocialIssueTest extends TestCase
{
    public function testFindSocialIssuesAncestors()
    {
        $socialIssues = new ArrayCollection([
            $parent = new SocialIssue(),
            $child = (new SocialIssue())->setParent($parent),
            $grandChild = (new SocialIssue())->setParent($child),
            $grandGrandChild = (new SocialIssue())->setParent($grandChild),
            $unrelated = new SocialIssue(),
        ]);

        $ancestors = SocialIssue::findAncestorSocialIssues($socialIssues);

        $this->assertCount(3, $ancestors);
        $this->assertContains($parent, $ancestors);
        $this->assertContains($child, $ancestors);
        $this->assertContains($grandChild, $ancestors);
    }

    public function testGetAncestors()
    {
        $parent = new SocialIssue();
        $child = (new SocialIssue())->setParent($parent);
        $grandChild = (new SocialIssue())->setParent($child);
        $grandGrandChild = (new SocialIssue())->setParent($grandChild);
        $unrelated = new SocialIssue();

        $this->assertContains($parent, $grandGrandChild->getAncestors(true));
        $this->assertContains($child, $grandGrandChild->getAncestors(true));
        $this->assertContains($grandChild, $grandGrandChild->getAncestors(true));
        $this->assertContains($grandGrandChild, $grandGrandChild->getAncestors(true));
        $this->assertNotContains($grandGrandChild, $grandGrandChild->getAncestors(false));
        $this->assertCount(0, $unrelated->getAncestors(false));
    }

    public function testGetDescendantsWithThisForIssues()
    {
        $parentA = new SocialIssue();
        $childA = (new SocialIssue())->setParent($parentA);
        $grandChildA = (new SocialIssue())->setParent($childA);
        $grandGrandChildA = (new SocialIssue())->setParent($grandChildA);
        $unrelatedA = new SocialIssue();

        $parentB = new SocialIssue();
        $childB = (new SocialIssue())->setParent($parentB);
        $grandChildB = (new SocialIssue())->setParent($childB);
        $grandGrandChildB = (new SocialIssue())->setParent($grandChildB);
        $unrelatedB = new SocialIssue();

        $actual = SocialIssue::getDescendantsWithThisForIssues([$parentA, $parentB]);

        $this->assertContains($parentA, $actual);
        $this->assertContains($parentB, $actual);
        $this->assertContains($childA, $actual);
        $this->assertContains($childB, $actual);
        $this->assertContains($grandChildA, $actual);
        $this->assertContains($grandChildB, $actual);
        $this->assertContains($grandGrandChildA, $actual);
        $this->assertContains($grandGrandChildB, $actual);
        $this->assertCount(8, $actual);
        $this->assertNotContains($unrelatedA, $actual);
        $this->assertNotContains($unrelatedB, $actual);
    }

    public function testIsDescendantOf()
    {
        $parent = new SocialIssue();
        $child = (new SocialIssue())->setParent($parent);
        $grandChild = (new SocialIssue())->setParent($child);
        $grandGrandChild = (new SocialIssue())->setParent($grandChild);
        $unrelated = new SocialIssue();

        $this->assertTrue($grandGrandChild->isDescendantOf($parent));
        $this->assertTrue($grandGrandChild->isDescendantOf($grandChild));
        $this->assertTrue($grandGrandChild->isDescendantOf($child));
        $this->assertFalse($grandGrandChild->isDescendantOf($unrelated));

        $this->assertTrue($grandChild->isDescendantOf($parent));
        $this->assertTrue($grandChild->isDescendantOf($child));
        $this->assertFalse($grandChild->isDescendantOf($unrelated));
        $this->assertFalse($grandChild->isDescendantOf($grandChild));

        $this->assertFalse($unrelated->isDescendantOf($parent));

        $this->assertFalse($child->isDescendantOf($grandChild));
    }
}
