<?php declare(strict_types=1);

namespace Newland\Toubiz\Services\Neos\LinkHandler;

use Neos\ContentRepository\Domain\Model\NodeInterface;
use Neos\Flow\Annotations as Flow;
use Neos\Flow\I18n\Locale;
use Neos\Flow\I18n\Translator;
use Neos\Flow\Mvc\Controller\ControllerContext;
use Newland\NeosCommon\LinkHandler\Domain\Model\Record;
use Newland\NeosCommon\LinkHandler\Handler\AbstractLinkHandler;
use Newland\Toubiz\Services\Neos\Service\ServiceUrlService;
use Newland\Toubiz\Sync\Neos\Domain\Model\Service;
use Newland\Toubiz\Sync\Neos\Domain\Repository\ServiceRepository;

class ServiceLinkHandler extends AbstractLinkHandler
{

    /**
     * @var ServiceRepository
     * @Flow\Inject()
     */
    protected $serviceRepository;

    /**
     * @var ServiceUrlService
     * @Flow\Inject()
     */
    protected $serviceUrlService;

    /**
     * @var Translator
     * @Flow\Inject()
     */
    protected $translator;

    public function findByIdentifier(string $recordIdentifier): ?Record
    {
        return $this->identifierToRecord($recordIdentifier);
    }

    public function findBySearchTerm(string $searchTerm): array
    {
        $services = $this->serviceRepository->withLanguage(
            $this->language,
            function () use ($searchTerm) {
                return $this->serviceRepository
                    ->createQueryBuilder('service')
                    ->where('service.name LIKE :term')
                    ->setParameter('term', sprintf('%%%s%%', $searchTerm))
                    ->setMaxResults(10)
                    ->getQuery()
                    ->execute();
            }
        );

        return array_map([ $this, 'serviceToRecord' ], $services);
    }

    public function generateRecordLink(
        Record $record,
        ControllerContext $controllerContext,
        NodeInterface $contextNode,
        bool $absolute
    ): ?string {
        if (!($record instanceof ServiceRecord)) {
            $record = $this->identifierToRecord($record->getId());
            if (!$record) {
                return null;
            }
        }

        return $this->serviceUrlService->generateUrl($record->getService());
    }

    protected function serviceToRecord(Service $service): ServiceRecord
    {
        $record = new ServiceRecord($service);
        $type = $this->translator->translateById(
            'singular',
            [],
            null,
            $this->language ? new Locale($this->language) : null,
            'Models/Service',
            'Newland.Toubiz.Services.Neos'
        );
        if ($type) {
            $record->setTitle(sprintf('%s [%s]', $service->getName(), $type));
        }
        return $record;
    }

    protected function identifierToRecord(string $recordIdentifier): ?ServiceRecord
    {
        $service = $this->serviceRepository->findByIdentifier($recordIdentifier);
        if ($service === null) {
            return null;
        }

        return $this->serviceToRecord($service);
    }
}
