<?php

declare(strict_types=1);

namespace CpCreation\VitiCore\Tests\Mailer;

use CpCreation\VitiCore\Bridge\Symfony\Bundle\Mailer\EmailLogMetadata;
use CpCreation\VitiCore\Bridge\Symfony\Bundle\Mailer\ReviewInvitationMailer;
use CpCreation\VitiCore\Contact\Model\Contact;
use CpCreation\VitiCore\Contact\Repository\ContactRepository;
use CpCreation\VitiCore\Marketing\Model\ReviewRequestConfiguration;
use CpCreation\VitiCore\Marketing\Model\Translation\ReviewRequestConfigurationTranslation;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Mailer\Transport\TransportInterface;
use Symfony\Component\Mime\Email;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
use Twig\Environment;

final class ReviewInvitationMailerTest extends TestCase
{
    public function testTestEmailUsesFakeOrderAndRequestedRecipient(): void
    {
        $contact = new Contact();
        $contact->setCompany('Domaine Exemple');
        $contact->setEmailFrom('contact@example.com');

        $contactRepository = $this->createMock(ContactRepository::class);
        $contactRepository->method('findOne')->willReturn($contact);

        $renderedContexts = [];
        $twig = $this->createMock(Environment::class);
        $twig->method('render')->willReturnCallback(
            static function (string $template, array $context) use (&$renderedContexts): string {
                $renderedContexts[$template] = $context;

                return $template;
            },
        );

        $translator = $this->createMock(TranslatorInterface::class);
        $translator->method('trans')->willReturnCallback(
            static fn(string $id, array $parameters = []): string => match ($id) {
                'marketing.review_request.mail.subject' => 'Domaine Exemple aimerait connaître votre avis ⭐',
                'marketing.test_email.subject' => '[TEST] ' . $parameters['%subject%'],
                'marketing.test_email.fake.review_product' => 'Cuvée Réserve 75 cl',
                default => $id,
            },
        );

        $urlGenerator = $this->createMock(UrlGeneratorInterface::class);
        $urlGenerator->method('generate')->willReturnCallback(
            static fn(string $route): string => 'https://example.test/' . $route,
        );

        $sentEmail = null;
        $transport = $this->createMock(TransportInterface::class);
        $transport->expects(self::once())
            ->method('send')
            ->willReturnCallback(static function (Email $email) use (&$sentEmail): null {
                $sentEmail = $email;

                return null;
            });

        $mailer = new ReviewInvitationMailer(
            $transport,
            $contactRepository,
            $translator,
            $twig,
            $urlGenerator,
        );
        $configuration = new ReviewRequestConfiguration();
        $translation = $configuration->translate('fr');
        self::assertInstanceOf(ReviewRequestConfigurationTranslation::class, $translation);
        $translation->setEmailTitle('Partagez votre expérience');
        $mailer->sendTest('admin@example.com', $configuration);

        self::assertInstanceOf(Email::class, $sentEmail);
        self::assertSame('admin@example.com', $sentEmail->getTo()[0]->getAddress());
        self::assertSame(
            '[TEST] Domaine Exemple aimerait connaître votre avis ⭐',
            $sentEmail->getSubject(),
        );
        self::assertSame('review_invitation_test', EmailLogMetadata::read($sentEmail)['type'] ?? null);
        self::assertCount(2, $renderedContexts);
        foreach ($renderedContexts as $context) {
            self::assertSame('TEST-AVIS', $context['cart']['token']);
            self::assertSame('Cuvée Réserve 75 cl', $context['cart']['items'][0]['variant']['fullName']);
            self::assertSame('Partagez votre expérience', $context['email_title']);
            self::assertFalse($context['is_reminder']);
        }
    }
}
