<?php
declare(strict_types=1);

namespace App\Tests\Unit\Service\Mailer\Builder;

use App\Entity\Access\Access;
use App\Entity\Organization\Organization;
use App\Entity\Organization\Subdomain;
use App\Repository\Access\AccessRepository;
use App\Repository\Organization\OrganizationRepository;
use App\Repository\Organization\SubdomainRepository;
use App\Service\Access\Utils as AccessUtils;
use App\Service\Mailer\Builder\OnSubdomainChangeMailBuilder;
use App\Service\Mailer\Email;
use App\Service\Mailer\Mailer;
use App\Service\Mailer\Model\SubdomainChangeModel;
use Doctrine\ORM\EntityManagerInterface;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;

/**
 * Classe OnSubdomainChangeMailBuilderTest qui test le service SubDomainChangeBuilder
 */
class OnSubdomainChangeMailBuilderTest extends TestCase
{
    private MockObject|EntityManagerInterface $entityManager;
    private string $opentalentNoReplyEmailAddress = 'no-reply@opentalent.fr';
    private MockObject|AccessUtils $accessUtils;

    public function setUp(): void
    {
        $this->entityManager = $this->getMockBuilder(EntityManagerInterface::class)->disableOriginalConstructor()->getMock();
        $this->accessUtils = $this->getMockBuilder(AccessUtils::class)->disableOriginalConstructor()->getMock();
    }

    /**
     * subDomainChangeBuilder mock maker
     * @param string $methodUnderTest
     * @return Mailer|MockObject
     */
    private function makeSubDomainChangeBuilderMock(string $methodUnderTest): OnSubdomainChangeMailBuilder | MockObject
    {
        return $this->getMockBuilder(OnSubdomainChangeMailBuilder::class)
            ->setConstructorArgs([
                $this->entityManager,
                $this->opentalentNoReplyEmailAddress,
                $this->accessUtils
            ])
            ->setMethodsExcept([$methodUnderTest])
            ->getMock();
    }

    /**
     * @see OnSubdomainChangeMailBuilder::build()
     */
    public function testBuild()
    {
        $subdomainId = 123;
        $organizationId = 444;
        $senderId = 333;

        $subDomainChangeBuilder = $this->makeSubDomainChangeBuilderMock('build');

        $subdomain = $this->getMockBuilder(Subdomain::class)->disableOriginalConstructor()->getMock();
        $organization = $this->getMockBuilder(Organization::class)->disableOriginalConstructor()->getMock();
        $organization->method('getName')->willReturn('Mon organisation');
        $access = $this->getMockBuilder(Access::class)->disableOriginalConstructor()->getMock();

        $mailerModel = $this->getMockBuilder(SubdomainChangeModel::class)->disableOriginalConstructor()->getMock();
        $mailerModel->method('getSubdomainId')->willReturn($subdomainId);
        $mailerModel->method('getOrganizationId')->willReturn($organizationId);
        $mailerModel->method('getSenderId')->willReturn($senderId);

        $subdomainRepository = $this->getMockBuilder(SubdomainRepository::class)->disableOriginalConstructor()->getMock();
        $subdomainRepository->expects(self::once())->method('find')->with($subdomainId)->willReturn($subdomain);
        $organizationRepository = $this->getMockBuilder(OrganizationRepository::class)->disableOriginalConstructor()->getMock();
        $organizationRepository->expects(self::once())->method('find')->with($organizationId)->willReturn($organization);
        $accessRepository = $this->getMockBuilder(AccessRepository::class)->disableOriginalConstructor()->getMock();
        $accessRepository->expects(self::once())->method('find')->with($senderId)->willReturn($access);

        $this->entityManager
            ->expects(self::exactly(3))
            ->method('getRepository')
            ->withConsecutive([Subdomain::class], [Organization::class], [Access::class])
            ->willReturnOnConsecutiveCalls($subdomainRepository, $organizationRepository, $accessRepository)
            ;

        $this->accessUtils
            ->expects(self::once())
            ->method('findAdminFor')
            ->with($organization)
            ->willReturn($access)
        ;

        $context = [
            'access' => $access,
            'organization' => $organization,
            'subdomain' => $subdomain,
            'url' => $mailerModel->getUrl()
        ];
        $content = 'contenu';
        $subDomainChangeBuilder
            ->expects(self::once())
            ->method('render')
            ->with('subdomain', $context)
            ->willReturn($content)
        ;

        $emailsCollection = $subDomainChangeBuilder->build($mailerModel);

        $this->assertCount(1, $emailsCollection);
        $email = $emailsCollection->first();
        $this->assertInstanceOf(Email::class, $email);
        $this->assertEquals('contenu', $email->getContent());
        $this->assertEquals($this->opentalentNoReplyEmailAddress, $email->getFrom());
        $this->assertEquals($organization->getName(), $email->geFromName());
    }
}
