<?php

namespace App\Service\OnChange\Organization;

use App\Entity\Organization\Organization;
use App\Entity\Organization\Subdomain;
use App\Message\Command\MailerCommand;
use App\Message\Command\Typo3\Typo3UpdateCommand;
use App\Service\Access\Utils as AccessUtils;
use App\Service\Mailer\Model\SubdomainChangeModel;
use App\Service\MailHub;
use App\Service\OnChange\OnChangeContext;
use App\Service\OnChange\OnChangeDefault;
use App\Service\Organization\Utils as OrganizationUtils;
use App\Service\Typo3\BindFileService;
use App\Tests\Service\OnChange\Organization\OnSubdomainChangeTest;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Messenger\MessageBusInterface;
use Symfony\Component\Security\Core\Security;

class OnSubdomainChange extends OnChangeDefault
{
    public function __construct(
        private OrganizationUtils $organizationUtils,
        private BindFileService $bindFileService,
        private MessageBusInterface $messageBus,
        private Security $security,
        private EntityManagerInterface $em
    ) {}

    /** @noinspection PhpParameterNameChangedDuringInheritanceInspection */
    public function validate($subdomain, OnChangeContext $context): void {
        // Ensure we do not exceed the limit of 3 subdomains per organization
        if (
            $context->isPostRequest() &&
            count($subdomain->getOrganization()->getSubdomains()) >= 3
        ) {
            throw new \RuntimeException('This organization has already registered 3 subdomains');
        }
    }

    /** @noinspection PhpParameterNameChangedDuringInheritanceInspection */
    public function beforeChange($subdomain, OnChangeContext $context): void
    {
        // Ensure it is the only active subdomain of this organization by disabling other organization subdomains
        if ($subdomain->isActive()) {
            foreach ($subdomain->getOrganization()->getSubdomains() as $other) {
                if ($other !== $subdomain && $other->isActive()) {
                    $other->setActive(false);
                }
            }
        }
    }

    /** @noinspection PhpParameterNameChangedDuringInheritanceInspection */
    public function onChange($subdomain, OnChangeContext $context): void {
        // Register into the BindFile
        if ($context->isPostRequest()) {
            $this->bindFileService->registerSubdomain($subdomain->getSubdomain());
        }

        // A new subdomain is active
        // /!\ This has to be executed after everything has been persisted
        if ($subdomain->isActive() && !($context->previousData() && $context->previousData()->isActive())) {
            // TODO: comprendre pourquoi ce refresh est indispensable pour le l'organisation soit à jour
            $this->em->refresh($subdomain->getOrganization());

            // Update the typo3 website (asynchronously with messenger)
            $this->messageBus->dispatch(
                new Typo3UpdateCommand($subdomain->getOrganization()->getId())
            );

            // Envoi d'un email
            $this->sendEmailAfterSubdomainChange($subdomain);
        }
    }

    /**
     * @param Subdomain $subdomain
     * @see OnSubdomainChangeTest::testSendEmailAfterSubdomainChange()
     */
    public function sendEmailAfterSubdomainChange(Subdomain $subdomain): void
    {
        $this->messageBus->dispatch(
            new MailerCommand($this->getMailModel($subdomain))
        );
    }

    /**
     * @param Subdomain $subdomain
     * @return SubdomainChangeModel
     * @see OnSubdomainChangeTest::testGetMailModel()
     */
    public function getMailModel(Subdomain $subdomain): SubdomainChangeModel{
        return (new SubdomainChangeModel())
            ->setSenderId($this->security->getUser()->getId())
            ->setOrganizationId($subdomain->getOrganization()->getId())
            ->setSubdomainId($subdomain->getId())
            ->setUrl($this->organizationUtils->getOrganizationWebsite($subdomain->getOrganization()));
    }
}
