<?php
declare(strict_types=1);

namespace App\Service\Access;

use App\ApiResources\Profile\AccessProfile;
use App\Entity\Access\Access;
use App\Repository\Access\AccessRepository;
use App\Service\Organization\OrganizationProfileCreator;
use App\Test\Service\Access\AccessProfileCreatorTest;
use Symfony\Component\Security\Core\Exception\AuthenticationException;

/**
 * Class AccessProfileCreator : Service contenant les manipulations associés à la ressource AccessProfile
 * @package App\Service\Access
 */
class AccessProfileCreator
{
    public function __construct(
        private OrganizationProfileCreator $organizationProfileCreator,
        private AccessRepository $accessRepository,
        private Utils $accessUtils
    )
    { }

    /**
     * On récupère l'accessProfile complet correspondant à l'Access
     * @param Access $access
     * @param Access $originalAccess
     * @return AccessProfile
     * @throws \Exception
     * @see AccessProfileCreatorTest::testGetAccessProfileFailed
     */
    public function getAccessProfile(Access $access, Access $originalAccess = null): AccessProfile
    {
        $validAccesses = $this->accessRepository->findAllValidAccesses($access);
        if(empty($validAccesses))
            throw new AuthenticationException('no_valid_access', 401);

        //L'Access en paramètre est celui de la connexion
        $mainAccessProfile = $this->createCompleteAccessProfile($access);

        //On remplit les accesses multi-compte
        $multiAccesses = $this->accessUtils->filterAccesses($validAccesses, $access);
        foreach ($multiAccesses as $multiAccess){
            $mainAccessProfile->addMultiAccess($this->organizationProfileCreator->createLightOrganizationProfile($multiAccess->getOrganization()));
        }

        //On remplit les accesses famille
        $familyAccesses = $access->getChildren();
        foreach ($familyAccesses as $familyAccess){
            $mainAccessProfile->addFamilyAccess($this->createLightAccessProfile($familyAccess));
        }

        //Dans le cas où nous sommes dans une connexion switch
        if($originalAccess){
            $mainAccessProfile->setOriginalAccess($this->createLightAccessProfile($originalAccess));
        }

        return $mainAccessProfile;
    }

    /**
     * Créer une ressource AccessProfile à partir d'une entité Access
     * @param Access $access
     * @return AccessProfile
     * @see AccessProfileCreatorTest::testCreateAccessProfile
     */
    public function createCompleteAccessProfile(Access $access): AccessProfile
    {
        $accessProfile = $this->createLightAccessProfile($access);
        return $accessProfile
            ->setIsAdminAccess($access->getAdminAccess())
            ->setRoles($this->accessUtils->getAllRoles($access))
            ->setHistorical($access->getHistorical())
            ->setOrganization($this->organizationProfileCreator->createCompleteOrganizationProfile($access->getOrganization()))
            ->setIsGuardian(!$access->getChildren()->isEmpty())
            ->setIsPayor(
                !$access->getBillingPayers()->isEmpty() ||
                ($access->getBillingReceivers()->isEmpty() && $access->getChildren()->isEmpty() && !$access->getAccessIntangibles()->isEmpty())
            )
            ;
    }

    /**
     * Classe permettant de créer et Setter les éléments de base d'une ressource AccessProfile à partir d'une entité Access
     * @param Access $access
     * @return AccessProfile
     * @see AccessProfileCreatorTest::testCreateLightAccessProfile()
     */
    public function createLightAccessProfile(Access $access): AccessProfile
    {
        $accessProfile = new AccessProfile();
        return $accessProfile
            ->setId($access->getId())
            ->setName($access->getPerson()->getName())
            ->setGivenName($access->getPerson()->getGivenName())
            ->setGender($access->getPerson()->getGender())
            ->setActivityYear($access->getActivityYear())
            ->setAvatarId($access->getPerson()->getImage()?->getId())
            ->setIsSuperAdminAccess($access->getSuperAdminAccess())
            ->setOrganization($this->organizationProfileCreator->createLightOrganizationProfile($access->getOrganization()))
            ;
    }
}