<?php

declare(strict_types=1);

namespace CpCreation\VitiCore\Bridge\Symfony\Bundle\Controller\Site;

use CpCreation\VitiCore\Cart\CartPromo;
use CpCreation\VitiCore\Cart\CartService;
use CpCreation\VitiCore\Cart\Repository\CartRepository;
use CpCreation\VitiCore\Marketing\Repository\AbandonedCartReminderRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Contracts\Translation\TranslatorInterface;

final class AbandonedCartRecoveryController extends AbstractController
{
    public function __construct(
        private readonly AbandonedCartReminderRepository $reminderRepository,
        private readonly CartRepository $cartRepository,
        private readonly CartService $cartService,
        private readonly TranslatorInterface $translator,
    ) {}

    public function __invoke(Request $request, string $token): Response
    {
        $reminder = $this->reminderRepository->findOneByToken($token);
        $now = new \DateTimeImmutable();

        if (null === $reminder || !$reminder->isUsableAt($now)) {
            $this->addFlash('error', $this->translator->trans('marketing.abandoned_cart.recovery.invalid'));

            return $this->redirectToRoute('shop');
        }

        $cart = $reminder->getCart();
        if ($cart->isCheckoutPayed() || $cart->isCheckoutOrdered() || $cart->getItems()->isEmpty()) {
            $reminder->cancel();
            $this->reminderRepository->save($reminder);
            $this->addFlash('info', $this->translator->trans('marketing.abandoned_cart.recovery.unavailable'));

            return $this->redirectToRoute('shop');
        }

        $promo = $reminder->getPromo();
        if (
            null !== $promo
            && (
                !$reminder->getRule()->isCouponOnlyWithoutExistingDiscount()
                || !$cart->hasExistingDiscount()
            )
            && !$promo->isDisabled()
            && (null === $promo->getEndAt() || $promo->getEndAt() > $now)
        ) {
            $cart->setPromoCodeInput($promo->getTitle());
        }

        if ($cart->getExpiresAt() <= $now) {
            $cart->setExpiresAt($reminder->getExpiresAt());
        }

        $this->cartRepository->save($cart);
        $request->getSession()->set('cart', $cart->getId()->toString());

        $resolvedCart = $this->cartService->getCart();
        if (null === $resolvedCart || !$resolvedCart->getId()->equals($cart->getId())) {
            $this->addFlash('error', $this->translator->trans('marketing.abandoned_cart.recovery.account_mismatch'));

            return $this->redirectToRoute('shop');
        }

        if (null === $promo && CartPromo::STATUS_INVALID === $resolvedCart->getPromoCodeStatus()) {
            $resolvedCart->setPromoCodeInput(null);
            $resolvedCart->clearPromoCodeFeedback();
            $this->cartService->hydratePromos($resolvedCart);
            $this->cartService->hydratePricing($resolvedCart);
            $this->cartRepository->save($resolvedCart);
        }

        $couponApplied = null !== $promo
            && CartPromo::STATUS_APPLIED === $resolvedCart->getPromoCodeStatus();

        $reminder->markRecovered($now);
        $this->reminderRepository->save($reminder);
        $this->addFlash('success', $this->translator->trans(
            $couponApplied
                ? 'marketing.abandoned_cart.recovery.success_with_coupon'
                : 'marketing.abandoned_cart.recovery.success',
        ));

        return $this->redirectToRoute('shop_checkout', [
            '_locale' => $cart->getLocale(),
        ]);
    }
}
