<?php

namespace NoahVet\Reef\Domain\Security\Policy\BSM;

use NoahVet\Reef\Domain\Business\Model\VeterinaryEstablishmentWithTeam;
use NoahVet\Reef\Domain\Security\Model\Resource;
use NoahVet\Reef\Domain\Security\Policy\AbstractPolicy;
use NoahVet\Reef\Domain\Security\Policy\PolicyResult;

/**
 * Policy abstraite pour les établissements vétérinaires avec équipe.
 *
 * Le développeur doit implémenter :
 * - {@see getResourceTypeSlug()} — slug IAM du type de ressource
 * - {@see getName()} — identifiant unique de la policy dans l'IAM
 * - {@see computeEtag()} — hash d'état de l'entité
 * - {@see apply()} — calcul des grants de permissions
 *
 * Le bundle enregistre automatiquement le ResourceFinder correspondant
 * dans le container Symfony via {@see WithTeamPoliciesCompilerPass}.
 *
 * @extends AbstractPolicy<VeterinaryEstablishmentWithTeam>
 */
abstract class AbstractVeterinaryEstablishmentWithTeamPolicy extends AbstractPolicy implements WithTeamPolicyInterface
{
    /**
     * Slug IAM du type de ressource (ex. "my:app:vet-establishment").
     * Utilisé par le CompilerPass pour configurer le ResourceFinder.
     */
    #[\Override]
    abstract public static function getResourceTypeSlug(): string;

    /** Identifiant unique de la policy dans l'IAM. */
    #[\Override]
    abstract public function getName(): string;

    /**
     * Hash d'état de l'entité — si identique au hash stocké dans l'IAM,
     * la synchronisation est ignorée.
     *
     * @param VeterinaryEstablishmentWithTeam $subject
     *
     * @return non-empty-string
     */
    #[\Override]
    abstract public function computeEtag(object $subject): string;

    /**
     * Calcule les grants de permissions pour l'entité.
     *
     * @param VeterinaryEstablishmentWithTeam $subject
     */
    #[\Override]
    abstract public function apply(object $subject): PolicyResult;

    #[\Override]
    final public function canHandle(object $subject): bool
    {
        return $subject instanceof VeterinaryEstablishmentWithTeam;
    }

    #[\Override]
    final public function subjectToString(object $subject): string
    {
        return static::getResourceTypeSlug().':'.$subject->getUuid();
    }

    /**
     * Crée la Resource IAM pour l'entité — à utiliser dans {@see apply()}.
     */
    final protected function createResource(VeterinaryEstablishmentWithTeam $subject): Resource
    {
        return Resource::fromString(static::getResourceTypeSlug(), $subject->getUuid());
    }
}
