<?php

declare(strict_types=1);

/*
 * Chill is a software for social workers
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */

namespace Chill\TaskBundle\Templating\UI;

use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Templating\UI\NotificationCounterInterface;
use Chill\TaskBundle\Repository\SingleTaskRepository;
use Psr\Cache\CacheItemPoolInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Workflow\Event\Event;

class CountNotificationTask implements NotificationCounterInterface
{
    final public const CACHE_KEY = 'chill_task.count_notifications.user.%d.%s';

    /**
     * @var CacheItempPoolInterface
     */
    protected $cachePool;

    /**
     * @var SingleTaskRepository
     */
    protected $singleTaskRepository;

    public function __construct(
        SingleTaskRepository $singleTaskRepository,
        CacheItemPoolInterface $cachePool,
    ) {
        $this->singleTaskRepository = $singleTaskRepository;
        $this->cachePool = $cachePool;
    }

    public function addNotification(UserInterface $u): int
    {
        return $this->countNotification($u);
    }

    public function countNotification(UserInterface $u): int
    {
        return
            $this->countNotificationEnded($u)
                + $this->countNotificationWarning($u);
    }

    public function countNotificationEnded(UserInterface $u): int
    {
        return $this->_countNotification($u, SingleTaskRepository::DATE_STATUS_ENDED);
    }

    public function countNotificationWarning(UserInterface $u): int
    {
        return $this->_countNotification($u, SingleTaskRepository::DATE_STATUS_WARNING);
    }

    public function resetCacheOnNewStates(Event $e)
    {
        /** @var \Chill\TaskBundle\Entity\SingleTask $task */
        $task = $e->getSubject();

        if (null !== $task->getAssignee()) {
            foreach (
                [
                    SingleTaskRepository::DATE_STATUS_ENDED,
                    SingleTaskRepository::DATE_STATUS_WARNING,
                ] as $status
            ) {
                $key = $this->getCacheKey($task->getAssignee(), $status);
                $sumCache = $this->cachePool->getItem($key);

                if ($sumCache->isHit()) {
                    $this->cachePool->deleteItem($key);
                }
            }
        }
    }

    protected function _countNotification(UserInterface $u, $status)
    {
        if (!$u instanceof User) {
            return 0;
        }

        $sumCache = $this->cachePool->getItem($this->getCacheKey($u, $status));

        if ($sumCache->isHit()) {
            return $sumCache->get();
        }

        $params = [
            'user' => $u,
            'is_closed' => false,
        ];

        $sum = $this->singleTaskRepository->countByParameters(
            [...$params, 'date_status' => $status]
        );

        $sumCache->set($sum);
        $this->cachePool->save($sumCache);

        return $sum;
    }

    private function getCacheKey(User $u, $status)
    {
        return sprintf(self::CACHE_KEY, $u->getId(), $status);
    }
}
