<?php

namespace NoahVet\Reef\Infrastructure\Security;

use NoahVet\Reef\Application\Business\AbstractWithTeamFactory;
use NoahVet\Reef\Domain\Security\Model\ResourceType;
use NoahVet\Reef\Domain\Security\Port\ResourceEnumeratorInterface;
use NoahVet\Reef\Domain\Security\Port\ResourceLocatorInterface;
use NoahVet\Reef\Iterator\Factory\ReefApiIteratorFactoryInterface;

/**
 * Adaptateur générique implémentant les deux ports de sécurité pour les entités WithTeam BSM.
 *
 * Les sous-classes passent les classes Jane de leur endpoint et de leur DTO de réponse —
 * le reste de la logique (pagination, batching, résolution par slug) est fourni ici.
 */
abstract class AbstractApiWithTeamResourceFinder implements ResourceEnumeratorInterface, ResourceLocatorInterface
{
    private const DEFAULT_BATCH_SIZE = 50;

    /**
     * @param class-string $entityEndpointClass Classe endpoint Jane, ex. GetAllVeterinaryEstablishment::class
     * @param class-string $entityResponseClass Classe DTO de réponse Jane, ex. VeterinaryEstablishmentResponse::class
     */
    public function __construct(
        protected readonly object $client,
        protected readonly string $entityEndpointClass,
        protected readonly string $entityResponseClass,
        protected readonly AbstractWithTeamFactory $factory,
        protected readonly ReefApiIteratorFactoryInterface $iteratorFactory,
        protected readonly ResourceType $resourceType,
    ) {
    }

    /**
     * Énumère toutes les entités WithTeam, enrichies avec leur équipe courante.
     */
    #[\Override]
    public function enumerate(): \Generator
    {
        $batch = [];

        $iterator = $this->iteratorFactory->create(
            $this->client,
            $this->entityEndpointClass,
            $this->entityResponseClass,
            [],
            self::DEFAULT_BATCH_SIZE,
        );

        $iterator->rewind();

        /** @var object $item */
        foreach ($iterator as $item) {
            $batch[] = $item;

            if (self::DEFAULT_BATCH_SIZE === \count($batch)) {
                foreach ($this->factory->createBatch($batch) as $result) {
                    yield $result;
                }
                $batch = [];
            }
        }

        if (!empty($batch)) {
            foreach ($this->factory->createBatch($batch) as $result) {
                yield $result;
            }
        }
    }

    /**
     * Retourne l'entité WithTeam correspondant au slug IAM, ou null si non trouvée.
     */
    #[\Override]
    public function findBySlug(string $slug): mixed
    {
        $iamPrefix = $this->resourceType->getSlug().':';

        if (!\str_starts_with($slug, $iamPrefix)) {
            return null;
        }

        $uuid = \str_replace($iamPrefix, '', $slug);

        $iterator = $this->iteratorFactory->create(
            $this->client,
            $this->entityEndpointClass,
            $this->entityResponseClass,
            ['id' => [$uuid]],
            1,
        );

        $iterator->rewind();

        /** @var object $item */
        foreach ($iterator as $item) {
            return $this->factory->create($item);
        }

        return null;
    }
}
