<?php
namespace Newland\NeosCommon\LinkHandler\Domain\Repository;

/*
 * This file is part of the "neos-common" package.
 *
 * For the full copyright and license information, please read the
 * LICENSE.txt file that was distributed with this source code.
 */

use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Query;
use Doctrine\ORM\QueryBuilder;
use Newland\NeosCommon\LinkHandler\Domain\Model\Record;
use Neos\Flow\Annotations as Flow;

/**
 * Class RecordRepository
 *
 * @Flow\Scope("singleton")
 */
class RecordRepository
{
    /**
     * @var EntityManagerInterface
     * @Flow\Inject()
     */
    protected $entityManager;

    /**
     * @param string $searchTerm
     * @param array $searchField
     * @return Record[]
     */
    public function findBySearchField(string $searchTerm, array $searchField)
    {
        /** @var QueryBuilder $queryBuilder */
        $queryBuilder = $this->entityManager->createQueryBuilder();
        $queryBuilder
            ->select($searchField['alias'] . '.Persistence_Object_Identifier AS id')
            ->addSelect($searchField['alias'] . '.' . $searchField['searchField'] . ' AS title')
            ->from($searchField['objectType'], $searchField['alias'])
            ->where(
                $queryBuilder->expr()->like(
                    $searchField['alias'] . '.' . $searchField['searchField'],
                    ':searchTerm'
                )
            )
            ->setParameter('searchTerm', '%' . $searchTerm . '%');

        foreach ($searchField['filter'] as $field => $value) {
            $queryBuilder
                ->andWhere(
                    $queryBuilder->expr()->like(
                        $searchField['alias'] . '.' . $field,
                        ':' . $field
                    )
                )
                ->setParameter($field, $value);
        }

        $results = $queryBuilder
            ->orderBy('title')
            ->getQuery()
            ->execute(null, Query::HYDRATE_ARRAY);

        return array_map(
            function (array $result) {
                return (new Record())->setId($result['id'])->setTitle($result['title']);
            },
            $results
        );
    }

    /**
     * @param string $identifier
     * @param array $queryParameters
     * @return Record|null
     */
    public function findByRecordIdentifier(string $identifier, array $queryParameters)
    {
        /** @var QueryBuilder $queryBuilder */
        $queryBuilder = $this->entityManager->createQueryBuilder();
        $queryBuilder
            ->select($queryParameters['alias'] . '.Persistence_Object_Identifier AS id')
            ->addSelect($queryParameters['alias'] . '.' . $queryParameters['searchField'] . ' AS title')
            ->from($queryParameters['objectType'], $queryParameters['alias'])
            ->where(
                $queryBuilder->expr()->like(
                    $queryParameters['alias'] . '.Persistence_Object_Identifier',
                    ':identifier'
                )
            )
            ->setParameter('identifier', $identifier)
            ->setMaxResults(1);

        $result = $queryBuilder->getQuery()->execute()[0] ?? null;
        if (!$result) {
            return null;
        }

        return (new Record())->setTitle($result['title'])->setId($result['id']);
    }
}
