<?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\TicketBundle\Security\Voter;

use Chill\TicketBundle\Entity\Comment;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;

/**
 * Check permissions on comments.
 *
 * - Adding a comment to the ticket requires to be allowed to write on the ticket;
 * - Only the user who created the comment is allowed to edit it;
 */
final class CommentVoter extends Voter
{
    public const CREATE = 'CHILL_TICKET_COMMENT_CREATE';
    public const EDIT = 'CHILL_TICKET_COMMENT_EDIT';
    public const READ = 'CHILL_TICKET_COMMENT_READ';

    private const ALL = [self::CREATE, self::EDIT, self::READ];

    public function __construct(private readonly AccessDecisionManagerInterface $decisionManager) {}

    protected function supports(string $attribute, $subject): bool
    {
        return $subject instanceof Comment && in_array($attribute, self::ALL, true);
    }

    protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token): bool
    {
        /* @var Comment $subject */
        return match ($attribute) {
            self::READ => !$subject->isDeleted() || $subject->getCreatedBy() === $token->getUser(),
            self::CREATE => $this->decisionManager->decide($token, [TicketVoter::WRITE], $subject->getTicket()),
            self::EDIT => $token->getUser() === $subject->getCreatedBy(),
            default => throw new \Symfony\Component\Security\Core\Exception\LogicException('Invalid attribute'),
        };
    }
}
