<?php

declare(strict_types=1);

/*
 * This file is part of the Ferienpass package.
 *
 * (c) Richard Henkenjohann <richard@ferienpass.online>
 *
 * For more information visit the project website <https://ferienpass.online>
 * or the documentation under <https://docs.ferienpass.online>.
 */

namespace Ferienpass\CoreBundle\Security\Voter;

use Ferienpass\CoreBundle\Entity\Dbafs;
use Ferienpass\CoreBundle\Entity\DbafsWithOffer;
use Ferienpass\CoreBundle\Entity\User;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;

final class DbafsVoter extends Voter
{
    protected function supports(string $attribute, mixed $subject): bool
    {
        return \in_array(strtolower($attribute), ['view'], true) && $subject instanceof Dbafs;
    }

    /**
     * @param Dbafs $subject
     */
    protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token, ?\Symfony\Component\Security\Core\Authorization\Voter\Vote $vote = null): bool
    {
        $user = $token->getUser();

        if (!$user instanceof User) {
            return false;
        }

        if ($user->isAdmin()) {
            return true;
        }

        if ($subject->getUploadedBy() === $user) {
            return true;
        }

        $userHosts = $user->getHosts()->toArray();

        // If attached to an offer the user has access to -> allowed
        if ($subject instanceof DbafsWithOffer) {
            foreach ($subject->getOffers() as $relation) {
                $offer = $relation->getOffer();
                foreach ($offer->getHosts() as $host) {
                    if (\in_array($host, $userHosts, true)) {
                        return true;
                    }
                }
            }
        }

        // If directly linked to hosts (e.g. logos) and the user belongs to those hosts -> allowed
        if (method_exists($subject, 'getHosts')) {
            foreach ($subject->getHosts() as $host) {
                if (\in_array($host, $userHosts, true)) {
                    return true;
                }
            }
        }

        return false;
    }
}
