<?php

namespace NoahVet\Reef\Test\A_Unit\Business\Enumerator;

use NoahVet\Reef\Business\Enumerator\EstablishmentWithLegalStructureEnumerator;
use NoahVet\Reef\Business\Enumerator\VeterinaryEstablishmentEnumerator;
use NoahVet\Reef\Business\Enumerator\VeterinaryEstablishmentTeamMembersEnumerator;
use NoahVet\Reef\Business\Model\EstablishmentWithLegalStructure;
use NoahVet\Reef\Business\Model\Factory\TeamMemberFactory;
use NoahVet\Reef\Business\Model\TeamMember;
use NoahVet\Reef\Jane\Model\IdResponse;
use NoahVet\Reef\Jane\Model\VeterinaryEstablishmentResponse;
use NoahVet\Reef\Jane\Model\VeterinaryEstablishmentUserResponse;
use NoahVet\Reef\Jane\Model\VeterinaryEstablishmentUserResponseUser;
use NoahVet\Reef\Jane\Model\VeterinaryEstablishmentUserResponseVeterinaryEstablishment;
use PHPUnit\Framework\TestCase;

class EstablishmentWithLegalStructureEnumeratorTest extends TestCase
{
    public function testEnumerateAll(): void
    {
        $legalStructure = new IdResponse();
        $legalStructure->setId('legal-structure-id');

        $establishment = new VeterinaryEstablishmentResponse();
        $establishment->setId('phpunit-establishment-id');
        $establishment->setPrivilegedCode('CODE1');
        $establishment->setLegalStructure($legalStructure);

        $teamMember = new TeamMember(
            'user-id',
            'jobtitle',
            null,
            null,
        );

        $establishmentEnumerator = $this->getMockBuilder(VeterinaryEstablishmentEnumerator::class)
            ->disableOriginalConstructor()
            ->getMock()
        ;
        $establishmentEnumerator
            ->expects($this->once())
            ->method('enumerateAll')
            ->willReturnCallback(
                static function () use ($establishment) {
                    yield $establishment;
                },
            )
        ;

        $teamMembersEnumerator = $this->getMockBuilder(VeterinaryEstablishmentTeamMembersEnumerator::class)
            ->disableOriginalConstructor()
            ->getMock()
        ;
        $teamMembersEnumerator
            ->expects($this->once())
            ->method('getTeamMembers')
            ->with([$establishment])
            ->willReturn(['phpunit-establishment-id' => [$this->buildUserResponse('user-id', 'jobtitle', 'phpunit-establishment-id')]])
        ;

        $teamMemberFactory = $this->getMockBuilder(TeamMemberFactory::class)
            ->disableOriginalConstructor()
            ->getMock()
        ;
        $teamMemberFactory
            ->expects($this->once())
            ->method('create')
            ->willReturn($teamMember)
        ;

        $enumerator = new EstablishmentWithLegalStructureEnumerator(
            $establishmentEnumerator,
            $teamMembersEnumerator,
            $teamMemberFactory,
        );

        $results = \iterator_to_array($enumerator->enumerateAll());

        self::assertCount(1, $results);
        self::assertInstanceOf(EstablishmentWithLegalStructure::class, $results[0]);
        self::assertEquals('phpunit-establishment-id', $results[0]->getUuid());
        self::assertEquals('CODE1', $results[0]->getCode());
        self::assertEquals('legal-structure-id', $results[0]->getLegalStructureId());
        self::assertCount(1, $results[0]->getTeamMembers());
        self::assertSame($teamMember, $results[0]->getTeamMembers()[0]);
    }

    public function testEnumerateAllWithNoEstablishments(): void
    {
        $establishmentEnumerator = $this->getMockBuilder(VeterinaryEstablishmentEnumerator::class)
            ->disableOriginalConstructor()
            ->getMock()
        ;
        $establishmentEnumerator
            ->expects($this->once())
            ->method('enumerateAll')
            ->willReturnCallback(static function () { yield from []; })
        ;

        $teamMembersEnumerator = $this->getMockBuilder(VeterinaryEstablishmentTeamMembersEnumerator::class)
            ->disableOriginalConstructor()
            ->getMock()
        ;
        $teamMembersEnumerator
            ->expects($this->never())
            ->method('getTeamMembers')
        ;

        $enumerator = new EstablishmentWithLegalStructureEnumerator(
            $establishmentEnumerator,
            $teamMembersEnumerator,
            $this->getMockBuilder(TeamMemberFactory::class)->disableOriginalConstructor()->getMock(),
        );

        $results = \iterator_to_array($enumerator->enumerateAll());

        self::assertEmpty($results);
    }

    private function buildUserResponse(string $userId, string $jobTitle, string $establishmentId): VeterinaryEstablishmentUserResponse
    {
        $user = new VeterinaryEstablishmentUserResponseUser();
        $user->setId($userId);

        $veRef = new VeterinaryEstablishmentUserResponseVeterinaryEstablishment();
        $veRef->setId($establishmentId);

        $response = new VeterinaryEstablishmentUserResponse();
        $response->setJobTitle($jobTitle);
        $response->setUser($user);
        $response->setVeterinaryEstablishment($veRef);

        return $response;
    }
}
