<?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\PersonBundle\PersonIdentifier;

use Chill\PersonBundle\Entity\Identifier\PersonIdentifierDefinition;
use Chill\PersonBundle\PersonIdentifier\Exception\EngineNotFoundException;
use Chill\PersonBundle\PersonIdentifier\Exception\PersonIdentifierDefinitionNotFoundException;
use Chill\PersonBundle\Repository\Identifier\PersonIdentifierDefinitionRepository;

final readonly class PersonIdentifierManager implements PersonIdentifierManagerInterface
{
    public function __construct(
        private iterable $engines,
        private PersonIdentifierDefinitionRepository $personIdentifierDefinitionRepository,
    ) {}

    /**
     * Build PersonIdentifierWorker's for all active definition.
     *
     * @return list<PersonIdentifierWorker>
     */
    public function getWorkers(): array
    {
        $workers = [];
        foreach ($this->personIdentifierDefinitionRepository->findByActive() as $definition) {
            try {
                $worker = $this->getEngine($definition->getEngine());
            } catch (EngineNotFoundException) {
                continue;
            }

            $workers[] = new PersonIdentifierWorker($worker, $definition);

        }

        return $workers;
    }

    public function buildWorkerByPersonIdentifierDefinition(int|PersonIdentifierDefinition $personIdentifierDefinition): PersonIdentifierWorker
    {
        if (is_int($personIdentifierDefinition)) {
            $id = $personIdentifierDefinition;
            $personIdentifierDefinition = $this->personIdentifierDefinitionRepository->find($id);
            if (null === $personIdentifierDefinition) {
                throw new PersonIdentifierDefinitionNotFoundException($id);
            }
        }

        return new PersonIdentifierWorker($this->getEngine($personIdentifierDefinition->getEngine()), $personIdentifierDefinition);
    }

    /**
     * @throw EngineNotFoundException
     */
    private function getEngine(string $name): PersonIdentifierEngineInterface
    {
        foreach ($this->engines as $engine) {
            if ($engine->getName() === $name) {
                return $engine;
            }
        }

        throw new EngineNotFoundException($name);
    }
}
