<?php

declare(strict_types=1);

namespace CpCreation\VitiCore\Tests\Mailer;

use PHPUnit\Framework\TestCase;
use Twig\Environment;
use Twig\Loader\FilesystemLoader;
use Twig\TwigFilter;
use Twig\TwigFunction;

final class AbandonedCartReminderTemplateTest extends TestCase
{
    public function testConfiguredTitleIsDisplayedInHtmlAndTextEmails(): void
    {
        $context = array_replace($this->context(), [
            'email_title' => 'Retrouvez votre sélection personnalisée',
        ]);
        $twig = $this->twig();

        self::assertStringContainsString(
            'Retrouvez votre sélection personnalisée',
            $twig->render('mail/abandoned_cart_reminder.html.twig', $context),
        );
        self::assertStringContainsString(
            'Retrouvez votre sélection personnalisée',
            $twig->render('mail/abandoned_cart_reminder.txt.twig', $context),
        );
    }

    public function testHtmlTemplateContainsDedicatedPreheader(): void
    {
        $content = $this->twig()->render(
            'mail/abandoned_cart_reminder.html.twig',
            $this->context(),
        );

        self::assertStringContainsString(
            'Retrouvez votre panier et finalisez votre commande en quelques instants.',
            $content,
        );
        self::assertStringContainsString('display:none; max-height:0; overflow:hidden;', $content);
    }

    public function testCartItemsDisplayUnitPriceAndKeepLineTotalAndSubtotal(): void
    {
        $twig = $this->twig();

        foreach ([
            $twig->render('mail/abandoned_cart_reminder.html.twig', $this->context()),
            $twig->render('mail/abandoned_cart_reminder.txt.twig', $this->context()),
        ] as $content) {
            self::assertMatchesRegularExpression('/2 ×\\s+24,00 €/', $content);
            self::assertGreaterThanOrEqual(2, substr_count($content, '48,00 €'));
            self::assertStringContainsString('Sous-total des produits', $content);
        }
    }

    public function testExistingCartDiscountsAreDisplayedSeparatelyFromReminderCoupon(): void
    {
        $context = $this->context();
        $twig = $this->twig();

        foreach ([
            $twig->render('mail/abandoned_cart_reminder.html.twig', $context),
            $twig->render('mail/abandoned_cart_reminder.txt.twig', $context),
        ] as $content) {
            self::assertStringContainsString('Vos remises déjà appliquées', $content);
            self::assertStringContainsString('-12,00 €', $content);
            self::assertStringContainsString('-6,00 €', $content);
            self::assertStringContainsString('FIDELITE', $content);
            self::assertStringContainsString('-5,00 €', $content);
            self::assertStringContainsString('Votre avantage personnel', $content);
            self::assertSame(1, substr_count($content, 'PANIER-RELANCE'));
        }
    }

    public function testDiscountSectionIsHiddenWhenCartHasNoExistingDiscount(): void
    {
        $context = array_replace($this->context(), [
            'cart_catalog_discount_ttc' => 0,
            'cart_degressive_discount_ttc' => 0,
            'existing_cart_promos' => [],
            'has_existing_cart_discounts' => false,
        ]);
        $twig = $this->twig();

        foreach ([
            $twig->render('mail/abandoned_cart_reminder.html.twig', $context),
            $twig->render('mail/abandoned_cart_reminder.txt.twig', $context),
        ] as $content) {
            self::assertStringNotContainsString('Vos remises déjà appliquées', $content);
            self::assertStringContainsString('Votre avantage personnel', $content);
            self::assertSame(1, substr_count($content, 'PANIER-RELANCE'));
        }
    }

    public function testCouponWarnsThatCartChangesCanMakeItInapplicable(): void
    {
        $twig = $this->twig();

        foreach ([
            $twig->render('mail/abandoned_cart_reminder.html.twig', $this->context()),
            $twig->render('mail/abandoned_cart_reminder.txt.twig', $this->context()),
        ] as $content) {
            self::assertStringContainsString(
                'Une modification de votre panier peut rendre ce code promo inapplicable',
                $content,
            );
        }
    }

    public function testPercentageCouponIsPresentedAsAdditionalWhenCartAlreadyHasDiscounts(): void
    {
        $context = $this->context();
        $context['promo'] = array_replace($context['promo'], [
            'amountTTC' => null,
            'percent' => 0.05,
        ]);
        $twig = $this->twig();

        foreach ([
            $twig->render('mail/abandoned_cart_reminder.html.twig', $context),
            $twig->render('mail/abandoned_cart_reminder.txt.twig', $context),
        ] as $content) {
            self::assertStringContainsString(
                'Bénéficiez de 5 % de remise supplémentaire sur votre panier.',
                $content,
            );
        }
    }

    public function testPercentageCouponKeepsDefaultWordingWhenCartHasNoExistingDiscount(): void
    {
        $context = array_replace($this->context(), [
            'cart_catalog_discount_ttc' => 0,
            'cart_degressive_discount_ttc' => 0,
            'existing_cart_promos' => [],
            'has_existing_cart_discounts' => false,
        ]);
        $context['promo'] = array_replace($context['promo'], [
            'amountTTC' => null,
            'percent' => 0.05,
        ]);
        $twig = $this->twig();

        foreach ([
            $twig->render('mail/abandoned_cart_reminder.html.twig', $context),
            $twig->render('mail/abandoned_cart_reminder.txt.twig', $context),
        ] as $content) {
            self::assertStringContainsString(
                'Bénéficiez de 5 % de remise sur votre panier.',
                $content,
            );
            self::assertStringNotContainsString('remise supplémentaire', $content);
        }
    }

    private function twig(): Environment
    {
        $twig = new Environment(new FilesystemLoader(
            __DIR__ . '/../../src/Bridge/Symfony/Bundle/Resources/views',
        ));
        $twig->addFilter(new TwigFilter(
            'trans',
            static fn(string $key, array $parameters = []): string => strtr(match ($key) {
                'marketing.abandoned_cart.mail.subject' => 'Vos coups de cœur sont toujours là',
                'marketing.abandoned_cart.mail.preheader' => 'Retrouvez votre panier et finalisez votre commande en quelques instants.',
                'marketing.abandoned_cart.mail.heading' => 'Vos coups de cœur sont toujours là',
                'marketing.abandoned_cart.mail.intro' => 'Votre sélection est toujours disponible chez %company%.',
                'marketing.abandoned_cart.mail.cart_heading' => 'Récapitulatif de votre panier',
                'marketing.abandoned_cart.mail.cart_quantity' => '%quantity% ×',
                'marketing.abandoned_cart.mail.cart_subtotal' => 'Sous-total des produits',
                'marketing.abandoned_cart.mail.existing_discounts_heading' => 'Vos remises déjà appliquées',
                'marketing.abandoned_cart.mail.coupon_heading' => 'Votre avantage personnel',
                'marketing.abandoned_cart.mail.fixed_discount' => 'Bénéficiez de %amount% € de remise.',
                'marketing.abandoned_cart.mail.percent_discount' => 'Bénéficiez de %percent% % de remise sur votre panier.',
                'marketing.abandoned_cart.mail.percent_discount_additional' => 'Bénéficiez de %percent% % de remise supplémentaire sur votre panier.',
                'marketing.abandoned_cart.mail.coupon_cart_change_warning' => 'Une modification de votre panier peut rendre ce code promo inapplicable si les conditions de l’offre ne sont plus respectées.',
                'marketing.abandoned_cart.mail.button' => 'Reprendre mon panier',
                'marketing.abandoned_cart.mail.expiry' => 'Ce lien est valable jusqu’au %date%.',
                'shop.discount' => 'Remise',
                'shop.discount_shipping' => 'Remise sur la livraison',
                'shop.of_which_degressive' => 'Dont remise dégressive',
                'shop.option_label' => 'Option',
                default => $key,
            }, $parameters),
        ));
        $twig->addFilter(new TwigFilter(
            'price_format',
            static fn(int $price): string => number_format($price / 100, 2, ',', ' '),
        ));
        $twig->addFilter(new TwigFilter(
            'imagine_filter',
            static fn(string $path): string => $path,
        ));
        $twig->addFunction(new TwigFunction(
            'asset',
            static fn(string $path): string => $path,
        ));
        $twig->addFunction(new TwigFunction(
            'absolute_url',
            static fn(string $path): string => $path,
        ));

        return $twig;
    }

    /**
     * @return array<string, mixed>
     */
    private function context(): array
    {
        return [
            'contact' => null,
            'company' => 'Domaine Exemple',
            'email_title' => 'Vos coups de cœur sont toujours là',
            'email_subject' => 'Vos coups de cœur sont toujours là',
            'email_preheader' => 'Retrouvez votre panier et finalisez votre commande en quelques instants.',
            'cart' => [
                'items' => [[
                    'variant' => ['fullName' => 'Cuvée Réserve'],
                    'selectedOptionName' => null,
                    'quantity' => 2,
                    'finalPriceTTC' => 2400,
                    'totalFinalTTC' => 4800,
                ]],
            ],
            'cart_subtotal_ttc' => 4800,
            'cart_catalog_discount_ttc' => 1200,
            'cart_degressive_discount_ttc' => 600,
            'cart_degressive_is_bottle_offered' => false,
            'existing_cart_promos' => [[
                'code' => 'FIDELITE',
                'percent' => 0.1,
                'discountItemsTTC' => 500,
                'discountShippingTTC' => 0,
            ]],
            'has_existing_cart_discounts' => true,
            'promo' => [
                'title' => 'PANIER-RELANCE',
                'amountTTC' => 1000,
                'percent' => null,
                'percentShippingCost' => null,
            ],
            'recovery_url' => 'https://example.test/panier/reprise',
            'expires_at' => new \DateTimeImmutable('2026-08-01'),
            'locale' => 'fr',
        ];
    }
}
