<?php

namespace NoahVet\Reef\Application\Security\UseCase;

use NoahVet\Reef\Application\Security\Service\PolicyOrchestratorInterface;
use NoahVet\Reef\Domain\Security\Port\PolicyResultPublisherInterface;
use NoahVet\Reef\Domain\Security\Port\PolicyResultStoreInterface;

/**
 * Syncs all applicable policies for a single subject to the IAM.
 * Skips policies whose etag has not changed since the last sync.
 */
class SyncPoliciesUseCase implements SyncPoliciesUseCaseInterface
{
    public function __construct(
        private readonly PolicyOrchestratorInterface $orchestrator,
        private readonly PolicyResultStoreInterface $store,
        private readonly PolicyResultPublisherInterface $publisher,
    ) {
    }

    #[\Override]
    public function sync(object $subject): void
    {
        foreach ($this->orchestrator->getPoliciesFor($subject) as $policy) {
            $storedEtag = $this->store->findEtag(
                $policy->getName(),
                $policy->subjectToString($subject),
            );

            if ($storedEtag !== $policy->computeEtag($subject)) {
                $this->publisher->publish($policy->apply($subject));
            }
        }
    }
}
