<?php

namespace App\Service;

use App\Entity\Prospect;
use App\Message\ProspectCreated;
use App\Repository\Prospect\ProspectRepositoryInterface;
use App\Service\DataGrid\DataGridInterface;
use Doctrine\ORM\EntityNotFoundException;
use Symfony\Component\Messenger\MessageBusInterface;
use Symfony\Component\Messenger\Stamp\DelayStamp;

final class ProspectService
{
    /**
     * @var ProspectRepositoryInterface
     */
    private $repository;
    /**
     * @var MessageBusInterface
     */
    private $messageBus;

    /**
     * ProspectService constructor.
     *
     * @param ProspectRepositoryInterface $repository
     */
    public function __construct(ProspectRepositoryInterface $repository, MessageBusInterface $messageBus)
    {
        $this->repository = $repository;
        $this->messageBus = $messageBus;
    }

    /**
     * @param int $id
     *
     * @return Prospect
     *
     * @throws EntityNotFoundException
     */
    public function get(int $id): Prospect
    {
        $prospect = $this->repository->findById($id);
        if (!$prospect) {
            throw new EntityNotFoundException('Prospect with id '.$id.' does not exist!');
        }

        return $prospect;
    }

    /**
     * @return array|null
     */
    public function getAll(): ?array
    {
        return $this->repository->findAll();
    }

    /**
     * @return array|null
     */
    public function getByGrid(DataGridInterface $dataGrid): ?array
    {
        $criteria = $this->getCriteria($dataGrid);

        return $this->repository->findBy(
            $criteria,
            [
                $dataGrid->getSorters()->first()->getSort() => $dataGrid->getSorters()->first()->getOrder(),
            ],
            $dataGrid->getNavigation()->getRpp(),
            $dataGrid->getNavigation()->getRpp() * $dataGrid->getNavigation()->getPage());
    }

    /**
     * @param DataGridInterface $dataGrid
     *
     * @return int
     */
    public function countByGrid(DataGridInterface $dataGrid): int
    {
        $criteria = $this->getCriteria($dataGrid);

        return $this->repository->count($criteria);
    }

    /**
     * @param Prospect $prospect
     *
     * @return Prospect
     */
    public function save(Prospect $prospect): Prospect
    {
        $this->repository->save($prospect);
        $this->messageBus->dispatch(new ProspectCreated($prospect->getId(), [new DelayStamp(10000)]));

        return $prospect;
    }

    /**
     * @param Prospect $prospect
     */
    public function delete(Prospect $prospect): void
    {
        $this->repository->delete($prospect);
    }

    public function getByEmail(string $email): ?Prospect
    {
        return $this->repository->getByEmail($email);
    }

    private function getCriteria(DataGridInterface $dataGrid): array
    {
        $criteria = [];

        if ($dataGrid->getFilters()->containsKey('q') && $dataGrid->getFilters()->get('q')->isValid()) {
            $criteria += ['q' => $dataGrid->getFilters()->get('q')->getValue()];
        }

        if ($dataGrid->getFilters()->containsKey('status') && $dataGrid->getFilters()->get('status')->isValid()) {
            $criteria += ['status' => $dataGrid->getFilters()->get('status')->getValue()];
        }

        if ($dataGrid->getFilters()->containsKey('topic') && $dataGrid->getFilters()->get('topic')->isValid()) {
            $criteria += ['topic' => $dataGrid->getFilters()->get('topic')->getValue()];
        }

        if ($dataGrid->getFilters()->containsKey('domain') && $dataGrid->getFilters()->get('domain')->isValid()) {
            $criteria += ['domain' => $dataGrid->getFilters()->get('domain')->getValue()];
        }

        if ($dataGrid->getFilters()->containsKey('TF') && $dataGrid->getFilters()->get('TF')->isValid()) {
            $criteria += ['TF' => $dataGrid->getFilters()->get('TF')->getValue()];
        }

        if ($dataGrid->getFilters()->containsKey('DA') && $dataGrid->getFilters()->get('DA')->isValid()) {
            $criteria += ['DA' => $dataGrid->getFilters()->get('DA')->getValue()];
        }

        if ($dataGrid->getFilters()->containsKey('CF') && $dataGrid->getFilters()->get('CF')->isValid()) {
            $criteria += ['CF' => $dataGrid->getFilters()->get('CF')->getValue()];
        }

        if ($dataGrid->getFilters()->containsKey('PA') && $dataGrid->getFilters()->get('PA')->isValid()) {
            $criteria += ['PA' => $dataGrid->getFilters()->get('PA')->getValue()];
        }

        if ($dataGrid->getFilters()->containsKey('score') && $dataGrid->getFilters()->get('score')->isValid()) {
            $criteria += ['score' => $dataGrid->getFilters()->get('score')->getValue()];
        }

        if ($dataGrid->getFilters()->containsKey('category') && $dataGrid->getFilters()->get('category')->isValid()) {
            $criteria += ['category' => $dataGrid->getFilters()->get('category')->getValue()];
        }

        return $criteria;
    }

    public function getByDomain(int $domainId)
    {
        return $this->repository->findBy(['domain' => [$domainId]]);
    }

    public function getTypes(): array
    {
        return array_unique(array_map(function ($item) { return ucfirst($item['type']); }, $this->repository->getTypes()));
    }

    public function getNotUpdatedLastMonth()
    {
        return $this->repository->getNotUpdatedLastMonth();
    }
}
