<?php

/*
 * This file is part of the VITICORE2 package.
 *
 * (c) CP Creation <web@cpcreation.fr>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace CpCreation\VitiCore\Marketing;

use CpCreation\VitiCore\Cart\Model\Cart;
use CpCreation\VitiCore\Cart\Model\Promo;
use CpCreation\VitiCore\Cart\Repository\PromoRepository;
use CpCreation\VitiCore\Marketing\Model\AbandonedCartRule;

final readonly class AbandonedCartPromoFactory
{
    public function __construct(
        private PromoRepository $promoRepository,
    ) {}

    public function create(
        AbandonedCartRule $rule,
        Cart $cart,
        string $recipientEmail,
        \DateTimeImmutable $beginAt,
        \DateTimeImmutable $endAt,
    ): ?Promo {
        if (
            !$rule->createsCoupon()
            || ($rule->isCouponOnlyWithoutExistingDiscount() && $cart->hasExistingDiscount())
        ) {
            return null;
        }

        $promo = new Promo();
        $promo->setTitle($this->generateUniqueCode());
        $promo->setBeginAt($beginAt);
        $promo->setEndAt($endAt);
        $promo->setAuto(false);
        $promo->setCumulative(true);
        $promo->setDisabled(false);
        $promo->setMaxCount(1);
        $promo->setMaxCountByCustomer(1);
        $promo->setMinSubtotalTTC($rule->getMinSubtotalTTC());
        $promo->setMaxSubtotalTTC($rule->getMaxSubtotalTTC());
        $promo->setRestrictedCountryCodes($rule->getCountryCodes());
        if (null !== $rule->getPriceGroup()) {
            $promo->addGroup($rule->getPriceGroup());
        }

        if (null !== $cart->getUser()) {
            $promo->setAssignedUser($cart->getUser());
        } else {
            $promo->setNotificationEmail($recipientEmail);
        }

        match ($rule->getDiscountType()) {
            AbandonedCartRule::DISCOUNT_FIXED => $promo->setAmountTTC($rule->getDiscountAmountTTC()),
            AbandonedCartRule::DISCOUNT_PERCENT => $promo->setPercent(
                null !== $rule->getDiscountPercent() ? $rule->getDiscountPercent() / 100 : null,
            ),
            AbandonedCartRule::DISCOUNT_FREE_SHIPPING => $promo->setPercentShippingCost(1.0),
            default => null,
        };

        return $promo;
    }

    private function generateUniqueCode(): string
    {
        for ($attempt = 0; $attempt < 10; ++$attempt) {
            $code = 'PANIER-' . mb_strtoupper(bin2hex(random_bytes(5)));

            if (null === $this->promoRepository->findPromoByCode($code)) {
                return $code;
            }
        }

        throw new \RuntimeException('Impossible de générer un code promotionnel unique pour la relance panier.');
    }
}
