<?php

namespace Comitium5\DesignerBundle\UseCase\Search;

use Comitium5\DesignerBundle\Form\DataTransformer\SuggestDataTransformer;
use Comitium5\DesignerBundle\Model\Interfaces\SearchRepositoryInterface;
use Comitium5\DesignerBundle\ValueObjects\SearchEntityObject;
use Comitium5\DesignerBundle\ValueObjects\SearchQueryObject;
use Comitium5\DesignerBundle\ValueObjects\SearchResultObject;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\PropertyAccess\PropertyAccess;

/**
 * Class SuggestSearchUseCase
 *
 * @author David Carrascosa <david@bab-soft.com>
 * @package Comitium5\DesignerBundle\UseCase\Search
 */
class SuggestSearchUseCase
{
    /**
     * @var SearchRepositoryInterface
     */
    protected $searchRepository;

    /**
     * @var SearchQueryObject
     */
    protected $searchQueryObject;

    /**
     * @var string
     */
    protected $labelProperties;

    /**
     * @var string
     */
    protected $property;

    /**
     * SuggestSearchUseCase constructor.
     *
     * @param SearchRepositoryInterface $searchRepository
     * @param SearchQueryObject $searchQueryObject
     * @param string $labelProperties
     * @param string $property
     */
    public function __construct(
        SearchRepositoryInterface $searchRepository,
        SearchQueryObject $searchQueryObject,
        string $labelProperties,
        string $property
    ) {
        $this->searchRepository = $searchRepository;
        $this->searchQueryObject = $searchQueryObject;
        $this->labelProperties = $labelProperties;
        $this->property = $property;
    }

    /**
     * @return JsonResponse
     * @throws \Exception
     */
    public function __invoke(): JsonResponse
    {
        $results = $this
            ->searchRepository
            ->search($this->searchQueryObject);

        return new JsonResponse($this->serialize($results));
    }

    /**
     * @param SearchResultObject $results
     *
     * @return array|array[]
     * @throws \Exception
     */
    protected function serialize(SearchResultObject $results): array
    {
        $data = [
            'results' => []
        ];

        foreach ($results->getResults() as $result) {
            $data['results'][] = [
                'description' => SuggestDataTransformer::resolveDataDescription($result),
                'enabled'     => $result->isSearchable(),
                'future'      => SuggestDataTransformer::resolveFuture($result),
                'date'        => SuggestDataTransformer::resolveEntityDate($result),
                'id'          => $result->getId(),
                'text'        => $this->buildText($result),
            ];
        }

        return $data;
    }

    /**
     * @param SearchEntityObject $entity
     *
     * @return string
     */
    protected function buildText(SearchEntityObject $entity): string
    {
        if (!empty($this->labelProperties)) {
            return SuggestDataTransformer::resolveLabelProperties(
                $entity,
                $this->labelProperties
            );
        }

        $accessor = PropertyAccess::createPropertyAccessor();

        return $accessor->getValue(
            $entity,
            $this->property
        );
    }
}