<?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\ThirdPartyBundle\Search;

use Chill\MainBundle\Pagination\PaginatorFactory;
use Chill\MainBundle\Search\SearchInterface;
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
use Chill\ThirdPartyBundle\Repository\ThirdPartyRepository;
use Chill\ThirdPartyBundle\Security\Voter\ThirdPartyVoter;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;

/**
 * Allow to search amongst parties.
 */
class ThirdPartySearch implements SearchInterface
{
    final public const NAME = '3party';

    /**
     * @var AuthorizationHelper
     */
    protected $authorizationHelper;

    /**
     * @var EntityManagerInterface
     */
    protected $em;

    /**
     * @var PaginatorFactory
     */
    protected $paginatorFactory;

    /**
     * @var TokenStorageInterface
     */
    protected $tokenStorage;

    public function __construct(
        EntityManagerInterface $em,
        TokenStorageInterface $tokenStorage,
        AuthorizationHelper $authorizationHelper,
        PaginatorFactory $paginatorFactory,
        private readonly ThirdPartyRepository $thirdPartyRepository,
    ) {
        $this->em = $em;
        $this->tokenStorage = $tokenStorage;
        $this->authorizationHelper = $authorizationHelper;
        $this->paginatorFactory = $paginatorFactory;
    }

    public function getOrder(): int
    {
        return 59866;
    }

    public function isActiveByDefault(): bool
    {
        return false;
    }

    public function renderResult(array $terms, $start = 0, $limit = 50, $options = [], $format = 'html')
    {
        $centers = $this->authorizationHelper
            ->getReachableCenters(
                $this->tokenStorage->getToken()->getUser(),
                ThirdPartyVoter::SHOW
            );
        $total = $this->count($centers, $terms);
        $paginator = $this->paginatorFactory->create($total);
        // replace types in terms by types in query
        $terms['types'] = $options[SearchInterface::REQUEST_QUERY_PARAMETERS]['t'];
        $terms['is_active'] = true;

        if ('json' === $format) {
            return [
                'results' => $this->thirdPartyRepository
                    ->findByMemberOfCenters(
                        $centers,
                        $start,
                        $limit,
                        $terms,
                        ['array', ['tp.id', 'tp.name AS text']]
                    ),
                'more' => $paginator->hasNextPage(),
            ];
        }
        // format "html"
        throw new \UnexpectedValueException('format html not supported');
    }

    public function supports($domain, $format): bool
    {
        return self::NAME === $domain && 'json' === $format;
    }

    protected function count($centers, $terms): int
    {
        return $this->thirdPartyRepository
            ->countByMemberOfCenters($centers, $terms);
    }
}
