<?php

namespace App\Tests\Service;

use App\Entity\ActionLog;
use App\Entity\Customer;
use App\Entity\Domain;
use App\Entity\DomainEmail;
use App\Entity\User;
use App\Entity\Website;
use App\Service\ActionService;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface;

#[AllowMockObjectsWithoutExpectations]
class ActionServiceTest extends TestCase
{
    private EntityManagerInterface&MockObject $em;
    private LoggerInterface&MockObject $logger;
    private ActionService $service;

    // ─── Helpers ───────────────────────────────────────────────────────────────

    private function makeCustomer(string $state = Customer::STATE_ACTIVE): Customer&MockObject
    {
        $customer = $this->createMock(Customer::class);
        $customer->method('getId')->willReturn(1);
        $customer->method('getEmail')->willReturn('client@example.com');
        $customer->method('getFullName')->willReturn('Acme SARL');
        $customer->method('getState')->willReturn($state);

        return $customer;
    }

    private function makeWebsite(string $state = Website::STATE_OPEN): Website&MockObject
    {
        $website = $this->createMock(Website::class);
        $website->method('getId')->willReturn(10);
        $website->method('getName')->willReturn('Mon Site');
        $website->method('getUuid')->willReturn('uuid-1234');
        $website->method('getState')->willReturn($state);

        return $website;
    }

    private function makeDomainEmail(string $state = 'active'): DomainEmail&MockObject
    {
        $email = $this->createMock(DomainEmail::class);
        $email->method('getId')->willReturn(20);
        $email->method('getFullEmail')->willReturn('contact@example.com');
        $email->method('getState')->willReturn($state);

        return $email;
    }

    /** Returns a repo stub that always responds to findBy with the given results. */
    private function makeRepo(array $results = []): EntityRepository&MockObject
    {
        $repo = $this->createMock(EntityRepository::class);
        $repo->method('findBy')->willReturn($results);

        return $repo;
    }

    /**
     * Build an EM mock whose getRepository() returns different repos per class.
     *
     * @param array<string, EntityRepository> $repoMap  class => repo
     */
    private function makeEmWithRepos(array $repoMap): EntityManagerInterface&MockObject
    {
        $em = $this->createMock(EntityManagerInterface::class);
        $em->method('getRepository')->willReturnCallback(
            static function (string $class) use ($repoMap) {
                return $repoMap[$class] ?? (new class extends EntityRepository {
                    public function __construct() {}
                    public function findBy(array $criteria, ?array $orderBy = null, $limit = null, $offset = null): array { return []; }
                });
            }
        );

        return $em;
    }

    // ─── setUp ─────────────────────────────────────────────────────────────────

    protected function setUp(): void
    {
        $this->em     = $this->createMock(EntityManagerInterface::class);
        $this->logger = $this->createMock(LoggerInterface::class);
        $this->service = new ActionService($this->em, $this->logger);
    }

    // ══════════════════════════════════════════════════════════════════════════
    // suspendCustomer
    // ══════════════════════════════════════════════════════════════════════════

    public function testSuspendCustomerSuccess(): void
    {
        $customer = $this->makeCustomer(Customer::STATE_ACTIVE);
        $customer->expects($this->once())->method('setState')->with(Customer::STATE_SUSPENDED);

        $website = $this->makeWebsite(Website::STATE_OPEN);
        $website->expects($this->once())->method('setState')->with(Website::STATE_SUSPENDED);

        $user   = $this->createMock(User::class);
        $domain = new Domain($this->createStub(Customer::class), 'example.com');

        $domainEmail = $this->makeDomainEmail('active');
        $domainEmail->expects($this->once())->method('setState')->with('suspended');

        $websiteRepo     = $this->makeRepo([$website]);
        $domainRepo      = $this->makeRepo([$domain]);
        $domainEmailRepo = $this->makeRepo([$domainEmail]);

        $em = $this->makeEmWithRepos([
            Website::class     => $websiteRepo,
            Domain::class      => $domainRepo,
            DomainEmail::class => $domainEmailRepo,
        ]);
        $em->expects($this->atLeastOnce())->method('persist')->with($this->isInstanceOf(ActionLog::class));
        $em->expects($this->atLeastOnce())->method('flush');

        $service = new ActionService($em, $this->logger);
        $result  = $service->suspendCustomer($customer, 'Impaye');

        $this->assertTrue($result);
    }

    public function testSuspendCustomerAlreadySuspended(): void
    {
        $customer = $this->makeCustomer(Customer::STATE_SUSPENDED);
        $customer->expects($this->never())->method('setState');

        $this->em->expects($this->once())->method('persist')->with($this->isInstanceOf(ActionLog::class));
        $this->em->expects($this->once())->method('flush');

        $result = $this->service->suspendCustomer($customer);

        $this->assertTrue($result);
    }

    public function testSuspendCustomerException(): void
    {
        $customer = $this->makeCustomer(Customer::STATE_ACTIVE);
        $customer->method('setState')->willThrowException(new \RuntimeException('DB error'));

        // EM must be able to persist/flush the two ActionLogs (initial log + error log)
        $this->em->expects($this->exactly(2))->method('persist')->with($this->isInstanceOf(ActionLog::class));
        $this->em->expects($this->exactly(2))->method('flush');

        $result = $this->service->suspendCustomer($customer);

        $this->assertFalse($result);
    }

    public function testSuspendCustomerWithNoDomains(): void
    {
        $customer = $this->makeCustomer(Customer::STATE_ACTIVE);
        $customer->expects($this->once())->method('setState')->with(Customer::STATE_SUSPENDED);

        $websiteRepo = $this->makeRepo([]);
        $domainRepo  = $this->makeRepo([]);

        $em = $this->makeEmWithRepos([
            Website::class => $websiteRepo,
            Domain::class  => $domainRepo,
        ]);
        $em->method('persist');
        $em->method('flush');

        $service = new ActionService($em, $this->logger);
        $result  = $service->suspendCustomer($customer, 'test');

        $this->assertTrue($result);
    }

    // ══════════════════════════════════════════════════════════════════════════
    // unsuspendCustomer
    // ══════════════════════════════════════════════════════════════════════════

    public function testUnsuspendCustomerSuccess(): void
    {
        $customer = $this->makeCustomer(Customer::STATE_SUSPENDED);
        $customer->expects($this->once())->method('setState')->with(Customer::STATE_ACTIVE);

        $website = $this->makeWebsite(Website::STATE_SUSPENDED);
        $website->expects($this->once())->method('setState')->with(Website::STATE_OPEN);

        $domain      = new Domain($this->createStub(Customer::class), 'example.com');
        $domainEmail = $this->makeDomainEmail('suspended');
        $domainEmail->expects($this->once())->method('setState')->with('active');

        $websiteRepo     = $this->makeRepo([$website]);
        $domainRepo      = $this->makeRepo([$domain]);
        $domainEmailRepo = $this->makeRepo([$domainEmail]);

        $em = $this->makeEmWithRepos([
            Website::class     => $websiteRepo,
            Domain::class      => $domainRepo,
            DomainEmail::class => $domainEmailRepo,
        ]);
        $em->expects($this->atLeastOnce())->method('persist')->with($this->isInstanceOf(ActionLog::class));
        $em->expects($this->atLeastOnce())->method('flush');

        $service = new ActionService($em, $this->logger);
        $result  = $service->unsuspendCustomer($customer, 'Paiement recu');

        $this->assertTrue($result);
    }

    public function testUnsuspendCustomerNotSuspended(): void
    {
        $customer = $this->makeCustomer(Customer::STATE_ACTIVE);
        $customer->expects($this->never())->method('setState');

        $this->em->expects($this->once())->method('persist')->with($this->isInstanceOf(ActionLog::class));
        $this->em->expects($this->once())->method('flush');

        $result = $this->service->unsuspendCustomer($customer);

        $this->assertTrue($result);
    }

    public function testUnsuspendCustomerException(): void
    {
        $customer = $this->makeCustomer(Customer::STATE_SUSPENDED);
        $customer->method('setState')->willThrowException(new \RuntimeException('DB error'));

        // initial log + error log
        $this->em->expects($this->exactly(2))->method('persist')->with($this->isInstanceOf(ActionLog::class));
        $this->em->expects($this->exactly(2))->method('flush');

        $result = $this->service->unsuspendCustomer($customer);

        $this->assertFalse($result);
    }

    public function testUnsuspendCustomerWithNoSites(): void
    {
        $customer = $this->makeCustomer(Customer::STATE_SUSPENDED);
        $customer->expects($this->once())->method('setState')->with(Customer::STATE_ACTIVE);

        $websiteRepo = $this->makeRepo([]);
        $domainRepo  = $this->makeRepo([]);

        $em = $this->makeEmWithRepos([
            Website::class => $websiteRepo,
            Domain::class  => $domainRepo,
        ]);
        $em->method('persist');
        $em->method('flush');

        $service = new ActionService($em, $this->logger);
        $result  = $service->unsuspendCustomer($customer);

        $this->assertTrue($result);
    }

    // ══════════════════════════════════════════════════════════════════════════
    // suspendWebsite
    // ══════════════════════════════════════════════════════════════════════════

    public function testSuspendWebsiteSuccess(): void
    {
        $customer = $this->makeCustomer();
        $website  = $this->makeWebsite(Website::STATE_OPEN);
        $website->expects($this->once())->method('setState')->with(Website::STATE_SUSPENDED);

        // flush() is called once in the public method + once inside log()
        $this->em->expects($this->atLeastOnce())->method('flush');
        $this->em->expects($this->once())->method('persist')->with($this->isInstanceOf(ActionLog::class));

        $this->service->suspendWebsite($website, $customer, 'Impaye');
    }

    public function testSuspendWebsiteAlreadySuspended(): void
    {
        $customer = $this->makeCustomer();
        $website  = $this->makeWebsite(Website::STATE_SUSPENDED);
        $website->expects($this->never())->method('setState');

        $this->em->expects($this->never())->method('flush');
        $this->em->expects($this->never())->method('persist');

        $this->service->suspendWebsite($website, $customer);
    }

    // ══════════════════════════════════════════════════════════════════════════
    // unsuspendWebsite
    // ══════════════════════════════════════════════════════════════════════════

    public function testUnsuspendWebsiteSuccess(): void
    {
        $customer = $this->makeCustomer();
        $website  = $this->makeWebsite(Website::STATE_SUSPENDED);
        $website->expects($this->once())->method('setState')->with(Website::STATE_OPEN);

        $this->em->expects($this->atLeastOnce())->method('flush');
        $this->em->expects($this->once())->method('persist')->with($this->isInstanceOf(ActionLog::class));

        $this->service->unsuspendWebsite($website, $customer, 'Paiement recu');
    }

    public function testUnsuspendWebsiteFromOpenState(): void
    {
        // unsuspendWebsite does NOT check current state — it always sets to OPEN
        $customer = $this->makeCustomer();
        $website  = $this->makeWebsite(Website::STATE_OPEN);
        $website->expects($this->once())->method('setState')->with(Website::STATE_OPEN);

        $this->em->expects($this->atLeastOnce())->method('flush');
        $this->em->expects($this->once())->method('persist')->with($this->isInstanceOf(ActionLog::class));

        $this->service->unsuspendWebsite($website, $customer);
    }

    // ══════════════════════════════════════════════════════════════════════════
    // suspendDomainEmail
    // ══════════════════════════════════════════════════════════════════════════

    public function testSuspendDomainEmailSuccess(): void
    {
        $customer    = $this->makeCustomer();
        $domainEmail = $this->makeDomainEmail('active');
        $domainEmail->expects($this->once())->method('setState')->with('suspended');

        $this->em->expects($this->atLeastOnce())->method('flush');
        $this->em->expects($this->once())->method('persist')->with($this->isInstanceOf(ActionLog::class));

        $this->service->suspendDomainEmail($domainEmail, $customer, 'Impaye');
    }

    public function testSuspendDomainEmailAlreadySuspended(): void
    {
        $customer    = $this->makeCustomer();
        $domainEmail = $this->makeDomainEmail('suspended');
        $domainEmail->expects($this->never())->method('setState');

        $this->em->expects($this->never())->method('flush');
        $this->em->expects($this->never())->method('persist');

        $this->service->suspendDomainEmail($domainEmail, $customer);
    }

    // ══════════════════════════════════════════════════════════════════════════
    // unsuspendDomainEmail
    // ══════════════════════════════════════════════════════════════════════════

    public function testUnsuspendDomainEmailSuccess(): void
    {
        $customer    = $this->makeCustomer();
        $domainEmail = $this->makeDomainEmail('suspended');
        $domainEmail->expects($this->once())->method('setState')->with('active');

        $this->em->expects($this->atLeastOnce())->method('flush');
        $this->em->expects($this->once())->method('persist')->with($this->isInstanceOf(ActionLog::class));

        $this->service->unsuspendDomainEmail($domainEmail, $customer, 'Paiement recu');
    }

    public function testUnsuspendDomainEmailAlwaysSetsActive(): void
    {
        // Like unsuspendWebsite, this always sets state — no guard
        $customer    = $this->makeCustomer();
        $domainEmail = $this->makeDomainEmail('active');
        $domainEmail->expects($this->once())->method('setState')->with('active');

        $this->em->expects($this->atLeastOnce())->method('flush');
        $this->em->expects($this->once())->method('persist')->with($this->isInstanceOf(ActionLog::class));

        $this->service->unsuspendDomainEmail($domainEmail, $customer);
    }

    // ══════════════════════════════════════════════════════════════════════════
    // disableCustomer
    // ══════════════════════════════════════════════════════════════════════════

    public function testDisableCustomerSuccess(): void
    {
        $customer = $this->makeCustomer(Customer::STATE_SUSPENDED);
        $customer->expects($this->once())->method('setState')->with(Customer::STATE_DISABLED);

        // log() + flush inside log, then flush inside try block
        $this->em->expects($this->once())->method('persist')->with($this->isInstanceOf(ActionLog::class));
        $this->em->expects($this->atLeastOnce())->method('flush');

        $result = $this->service->disableCustomer($customer, 'Resiliation');

        $this->assertTrue($result);
    }

    public function testDisableCustomerException(): void
    {
        $customer = $this->makeCustomer(Customer::STATE_SUSPENDED);
        $customer->method('setState')->willThrowException(new \RuntimeException('DB error'));

        // initial log + error log
        $this->em->expects($this->exactly(2))->method('persist')->with($this->isInstanceOf(ActionLog::class));
        $this->em->expects($this->exactly(2))->method('flush');

        $result = $this->service->disableCustomer($customer);

        $this->assertFalse($result);
    }

    public function testDisableCustomerDefaultReason(): void
    {
        $customer = $this->makeCustomer(Customer::STATE_ACTIVE);
        $customer->expects($this->once())->method('setState')->with(Customer::STATE_DISABLED);

        $this->em->method('persist');
        $this->em->method('flush');

        $result = $this->service->disableCustomer($customer);

        $this->assertTrue($result);
    }

    // ══════════════════════════════════════════════════════════════════════════
    // markForDeletion
    // ══════════════════════════════════════════════════════════════════════════

    public function testMarkForDeletionSuccess(): void
    {
        $customer = $this->makeCustomer(Customer::STATE_DISABLED);
        $customer->expects($this->once())->method('setState')->with(Customer::STATE_PENDING_DELETE);

        $this->em->expects($this->once())->method('persist')->with($this->isInstanceOf(ActionLog::class));
        $this->em->expects($this->atLeastOnce())->method('flush');

        // The method also calls $this->logger->critical() directly (outside log())
        $this->logger->expects($this->atLeastOnce())->method('critical');

        $result = $this->service->markForDeletion($customer, 'Resiliation contrat');

        $this->assertTrue($result);
    }

    public function testMarkForDeletionException(): void
    {
        $customer = $this->makeCustomer(Customer::STATE_DISABLED);
        $customer->method('setState')->willThrowException(new \RuntimeException('DB error'));

        // initial log + error log
        $this->em->expects($this->exactly(2))->method('persist')->with($this->isInstanceOf(ActionLog::class));
        $this->em->expects($this->exactly(2))->method('flush');

        $result = $this->service->markForDeletion($customer);

        $this->assertFalse($result);
    }

    public function testMarkForDeletionDefaultReason(): void
    {
        $customer = $this->makeCustomer(Customer::STATE_ACTIVE);
        $customer->expects($this->once())->method('setState')->with(Customer::STATE_PENDING_DELETE);

        $this->em->method('persist');
        $this->em->method('flush');
        $this->logger->method('critical');

        $result = $this->service->markForDeletion($customer);

        $this->assertTrue($result);
    }

    // ══════════════════════════════════════════════════════════════════════════
    // log() private — severity branches (exercised via public methods)
    // ══════════════════════════════════════════════════════════════════════════

    /**
     * suspendCustomer uses 'critical' severity → logger::critical()
     * This also tests the 'warning' branch via the "already suspended" path.
     */
    public function testLogSeverityCriticalBranch(): void
    {
        // The initial log in suspendCustomer for a non-suspended customer uses 'critical'
        $customer = $this->makeCustomer(Customer::STATE_ACTIVE);
        $customer->method('setState');

        $this->em->method('persist');
        $this->em->method('flush');
        $this->em->method('getRepository')->willReturn($this->makeRepo([]));

        $this->logger->expects($this->atLeastOnce())->method('critical');

        $this->service->suspendCustomer($customer, 'Test critical log');
    }

    public function testLogSeverityWarningBranch(): void
    {
        // suspendCustomer with already-suspended customer triggers 'warning' log
        $customer = $this->makeCustomer(Customer::STATE_SUSPENDED);

        $this->em->method('persist');
        $this->em->method('flush');

        $this->logger->expects($this->once())->method('warning');

        $this->service->suspendCustomer($customer);
    }

    public function testLogSeverityInfoBranch(): void
    {
        // unsuspendCustomer uses 'info' severity
        $customer = $this->makeCustomer(Customer::STATE_SUSPENDED);
        $customer->method('setState');

        $this->em->method('persist');
        $this->em->method('flush');
        $this->em->method('getRepository')->willReturn($this->makeRepo([]));

        $this->logger->expects($this->atLeastOnce())->method('info');

        $this->service->unsuspendCustomer($customer);
    }

    public function testLogSeverityWarningBranchForUnsuspend(): void
    {
        // unsuspendCustomer with non-suspended customer triggers 'warning' log
        $customer = $this->makeCustomer(Customer::STATE_ACTIVE);

        $this->em->method('persist');
        $this->em->method('flush');

        $this->logger->expects($this->once())->method('warning');

        $this->service->unsuspendCustomer($customer);
    }

    /**
     * The private log() method has a 'danger' severity branch that maps to logger::error().
     * We exercise it via reflection to ensure full method coverage.
     */
    public function testLogSeverityDangerBranchCallsLoggerError(): void
    {
        $customer = $this->makeCustomer(Customer::STATE_ACTIVE);

        $this->em->method('persist');
        $this->em->method('flush');

        // The 'danger' severity maps to $this->logger->error(...)
        $this->logger->expects($this->once())->method('error');

        $method = new \ReflectionMethod(ActionService::class, 'log');
        $method->setAccessible(true);
        $method->invoke(
            $this->service,
            ActionLog::ACTION_SUSPEND_CUSTOMER,
            $customer,
            'Test danger severity',
            'danger',
            true,
            [],
        );
    }

    // ══════════════════════════════════════════════════════════════════════════
    // logError() private — exercised via exception paths above + dedicated test
    // ══════════════════════════════════════════════════════════════════════════

    public function testLogErrorPersistsActionLogWithErrorMessage(): void
    {
        $customer = $this->makeCustomer(Customer::STATE_ACTIVE);
        $customer->method('setState')->willThrowException(new \InvalidArgumentException('Invalid state'));

        $persistedLogs = [];
        $this->em->method('persist')->willReturnCallback(
            static function (object $obj) use (&$persistedLogs): void {
                $persistedLogs[] = $obj;
            }
        );
        $this->em->method('flush');

        $this->service->disableCustomer($customer);

        // There should be 2 ActionLog entries: the initial info log, then the error log
        $this->assertCount(2, $persistedLogs);

        /** @var ActionLog $errorLog */
        $errorLog = $persistedLogs[1];
        $this->assertInstanceOf(ActionLog::class, $errorLog);
        $this->assertFalse($errorLog->isSuccess());
        $this->assertNotNull($errorLog->getErrorMessage());
        $this->assertStringContainsString('Invalid state', $errorLog->getErrorMessage());
    }

    // ══════════════════════════════════════════════════════════════════════════
    // Edge cases — log() with entityId branch (via suspendWebsite/suspendDomainEmail)
    // ══════════════════════════════════════════════════════════════════════════

    public function testSuspendWebsiteSetsEntityIdInActionLog(): void
    {
        $customer = $this->makeCustomer();
        $website  = $this->makeWebsite(Website::STATE_OPEN);
        $website->method('setState');

        $persistedLogs = [];
        $this->em->method('persist')->willReturnCallback(
            static function (object $obj) use (&$persistedLogs): void {
                $persistedLogs[] = $obj;
            }
        );
        $this->em->method('flush');

        $this->service->suspendWebsite($website, $customer);

        $this->assertCount(1, $persistedLogs);
        /** @var ActionLog $log */
        $log = $persistedLogs[0];
        $this->assertSame(ActionLog::ACTION_SUSPEND_WEBSITE, $log->getAction());
        $this->assertSame(10, $log->getEntityId());
        $this->assertSame('Website', $log->getEntityType());
    }

    public function testSuspendDomainEmailSetsEntityIdInActionLog(): void
    {
        $customer    = $this->makeCustomer();
        $domainEmail = $this->makeDomainEmail('active');
        $domainEmail->method('setState');

        $persistedLogs = [];
        $this->em->method('persist')->willReturnCallback(
            static function (object $obj) use (&$persistedLogs): void {
                $persistedLogs[] = $obj;
            }
        );
        $this->em->method('flush');

        $this->service->suspendDomainEmail($domainEmail, $customer);

        $this->assertCount(1, $persistedLogs);
        /** @var ActionLog $log */
        $log = $persistedLogs[0];
        $this->assertSame(ActionLog::ACTION_SUSPEND_DOMAIN_EMAIL, $log->getAction());
        $this->assertSame(20, $log->getEntityId());
        $this->assertSame('DomainEmail', $log->getEntityType());
    }

    // ══════════════════════════════════════════════════════════════════════════
    // suspendCustomer — multiple websites and domain emails
    // ══════════════════════════════════════════════════════════════════════════

    public function testSuspendCustomerSuspendsMultipleWebsitesAndEmails(): void
    {
        $customer = $this->makeCustomer(Customer::STATE_ACTIVE);
        $customer->method('setState');

        $website1 = $this->makeWebsite(Website::STATE_OPEN);
        $website1->expects($this->once())->method('setState')->with(Website::STATE_SUSPENDED);
        $website2 = $this->makeWebsite(Website::STATE_OPEN);
        $website2->expects($this->once())->method('setState')->with(Website::STATE_SUSPENDED);

        $domain      = new Domain($this->createStub(Customer::class), 'example.com');
        $domainEmail1 = $this->makeDomainEmail('active');
        $domainEmail1->expects($this->once())->method('setState')->with('suspended');
        $domainEmail2 = $this->makeDomainEmail('active');
        $domainEmail2->expects($this->once())->method('setState')->with('suspended');

        $websiteRepo     = $this->makeRepo([$website1, $website2]);
        $domainRepo      = $this->makeRepo([$domain]);
        $domainEmailRepo = $this->makeRepo([$domainEmail1, $domainEmail2]);

        $em = $this->makeEmWithRepos([
            Website::class     => $websiteRepo,
            Domain::class      => $domainRepo,
            DomainEmail::class => $domainEmailRepo,
        ]);
        $em->method('persist');
        $em->method('flush');

        $service = new ActionService($em, $this->logger);
        $result  = $service->suspendCustomer($customer, 'Test multi');

        $this->assertTrue($result);
    }

    // ══════════════════════════════════════════════════════════════════════════
    // unsuspendCustomer — multiple websites and domain emails
    // ══════════════════════════════════════════════════════════════════════════

    public function testUnsuspendCustomerUnsuspendsMultipleWebsitesAndEmails(): void
    {
        $customer = $this->makeCustomer(Customer::STATE_SUSPENDED);
        $customer->method('setState');

        $website1 = $this->makeWebsite(Website::STATE_SUSPENDED);
        $website1->expects($this->once())->method('setState')->with(Website::STATE_OPEN);
        $website2 = $this->makeWebsite(Website::STATE_SUSPENDED);
        $website2->expects($this->once())->method('setState')->with(Website::STATE_OPEN);

        $domain      = new Domain($this->createStub(Customer::class), 'example.com');
        $domainEmail1 = $this->makeDomainEmail('suspended');
        $domainEmail1->expects($this->once())->method('setState')->with('active');
        $domainEmail2 = $this->makeDomainEmail('suspended');
        $domainEmail2->expects($this->once())->method('setState')->with('active');

        $websiteRepo     = $this->makeRepo([$website1, $website2]);
        $domainRepo      = $this->makeRepo([$domain]);
        $domainEmailRepo = $this->makeRepo([$domainEmail1, $domainEmail2]);

        $em = $this->makeEmWithRepos([
            Website::class     => $websiteRepo,
            Domain::class      => $domainRepo,
            DomainEmail::class => $domainEmailRepo,
        ]);
        $em->method('persist');
        $em->method('flush');

        $service = new ActionService($em, $this->logger);
        $result  = $service->unsuspendCustomer($customer, 'Paiement recu');

        $this->assertTrue($result);
    }
}
