<?php

namespace KupShop\BonusProgramBundle\EventListener;

use KupShop\AdminBundle\Util\ActivityLog;
use KupShop\BonusProgramBundle\BonusProgramBundle;
use KupShop\BonusProgramBundle\Email\BonusPointsExpiryEmail;
use KupShop\BonusProgramBundle\Utils\BonusComputer;
use KupShop\KupShopBundle\Context\ContextManager;
use KupShop\KupShopBundle\Event\CronEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Contracts\Service\Attribute\Required;

class CronListener implements EventSubscriberInterface
{
    /** @var BonusComputer */
    protected $bonusUtils;

    protected BonusPointsExpiryEmail $expiryEmail;
    protected ContextManager $contextManager;

    public static function getSubscribedEvents()
    {
        return [
            CronEvent::RUN_EXPENSIVE => [
                ['activatePoints', 200],
                ['deletePoints', 200],
                ['sendPointsExpiryEmails', 200],
            ],
        ];
    }

    public function deletePoints()
    {
        $this->bonusUtils->deleteExpiredPoints();
    }

    /**
     * @var CronEvent
     */
    public function activatePoints(CronEvent $cronEvent)
    {
        $this->bonusUtils->activatePoints();
    }

    public function sendPointsExpiryEmails(): void
    {
        $dbcfg = \Settings::getDefault();

        $removeTime = $dbcfg->bonus_program['remove_time'] ?? null;
        $notifyTime = $dbcfg->bonus_program['expiry_email_time'] ?? null;

        if (!$removeTime || !$notifyTime || !$this->expiryEmail->isEnabled()) {
            return;
        }

        // if the user will lose points in $notifyTime days from now
        $usersToNotify = $this->bonusUtils->getPointsThatExpireIn($notifyTime, $removeTime);

        $sentEmails = [];
        $ignoredEmails = [];
        foreach ($usersToNotify as $notifyUser) {
            $user = \User::createFromId((int) $notifyUser['id_user']);

            if (!$user) {
                $ignoredEmails[] = ['id_user' => $notifyUser['id_user']];
                continue;
            }

            $isActive = ($user->figure ?? 'Y') === 'Y';
            if (!$isActive) {
                $ignoredEmails[] = ['id_user' => $notifyUser['id_user']];
                continue;
            }

            $this->contextManager->activateUser($user, function () use ($user, &$sentEmails) {
                $email = $this->expiryEmail
                    ->setUser($user)
                    ->getEmail();

                $sentEmails[] = [$email['to'] => $this->expiryEmail->sendEmail($email)];
            });
        }

        addActivityLog(ActivityLog::SEVERITY_NOTICE, ActivityLog::TYPE_SYNC, 'Odeslány emaily o expiraci bodů',
            ['sent_email' => $sentEmails, 'ignored' => $ignoredEmails],
            [BonusProgramBundle::LOG_TAG_BONUS_PROGRAM]
        );
    }

    /**
     * @required
     */
    public function setBonusUtils(BonusComputer $bonusUtils): CronListener
    {
        $this->bonusUtils = $bonusUtils;

        return $this;
    }

    #[Required]
    public function setExpiryEmail(BonusPointsExpiryEmail $expiryEmail): void
    {
        $this->expiryEmail = $expiryEmail;
    }

    #[Required]
    public function setContextManager(ContextManager $contextManager): void
    {
        $this->contextManager = $contextManager;
    }
}
