<?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\MainBundle\Workflow\Messenger;

use Chill\DocStoreBundle\Exception\ConversionWithSameMimeTypeException;
use Chill\DocStoreBundle\Exception\StoredObjectManagerException;
use Chill\DocStoreBundle\Service\StoredObjectToPdfConverter;
use Chill\MainBundle\Entity\Workflow\EntityWorkflow;
use Chill\MainBundle\Entity\Workflow\EntityWorkflowSend;
use Chill\MainBundle\Repository\Workflow\EntityWorkflowRepository;
use Chill\MainBundle\Workflow\EntityWorkflowManager;
use Psr\Log\LoggerInterface;
use Symfony\Bridge\Twig\Mime\TemplatedEmail;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Messenger\Exception\UnrecoverableMessageHandlingException;
use Symfony\Component\Messenger\Handler\MessageHandlerInterface;

final readonly class PostSendExternalMessageHandler implements MessageHandlerInterface
{
    public function __construct(
        private EntityWorkflowRepository $entityWorkflowRepository,
        private MailerInterface $mailer,
        private EntityWorkflowManager $workflowManager,
        private StoredObjectToPdfConverter $storedObjectToPdfConverter,
        private LoggerInterface $logger,
    ) {}

    public function __invoke(PostSendExternalMessage $message): void
    {
        $entityWorkflow = $this->entityWorkflowRepository->find($message->entityWorkflowId);

        if (null === $entityWorkflow) {
            throw new UnrecoverableMessageHandlingException(sprintf('Entity workflow with id %d not found', $message->entityWorkflowId));
        }

        $this->convertToPdf($entityWorkflow, $message->lang);

        foreach ($entityWorkflow->getCurrentStep()->getSends() as $send) {
            $this->sendEmailToDestinee($send, $message);
        }
    }

    private function convertToPdf(EntityWorkflow $entityWorkflow, string $locale): void
    {
        foreach ($entityWorkflow->getAttachments() as $attachment) {
            try {
                $this->storedObjectToPdfConverter->addConvertedVersion($attachment->getProxyStoredObject(), $locale);
            } catch (StoredObjectManagerException $e) {
                $this->logger->error('Error converting attachment to PDF', ['backtrace' => $e->getTraceAsString(), 'attachment_id' => $attachment->getId()]);
            } catch (ConversionWithSameMimeTypeException $e) {
                $this->logger->error('Error converting attachment to PDF: already at the same MIME type', ['backtrace' => $e->getTraceAsString(), 'attachment_id' => $attachment->getId()]);
            }
        }

        $storedObject = $this->workflowManager->getAssociatedStoredObject($entityWorkflow);

        if (null !== $storedObject) {
            try {
                $this->storedObjectToPdfConverter->addConvertedVersion($storedObject, $locale);
            } catch (StoredObjectManagerException $e) {
                $this->logger->error('Error converting stored object to PDF', ['backtrace' => $e->getTraceAsString(), 'stored_object_id' => $storedObject->getId(), 'workflow_id' => $entityWorkflow->getId()]);
            } catch (ConversionWithSameMimeTypeException $e) {
                $this->logger->error('Error converting stored object to PDF: already at the same MIME type', ['backtrace' => $e->getTraceAsString(), 'stored_object_id' => $storedObject->getId(), 'workflow_id' => $entityWorkflow->getId()]);
            }
        }
    }

    private function sendEmailToDestinee(EntityWorkflowSend $send, PostSendExternalMessage $message): void
    {
        $entityWorkflow = $send->getEntityWorkflowStep()->getEntityWorkflow();
        $title = $this->workflowManager->getHandler($entityWorkflow)->getEntityTitle($entityWorkflow);
        $email = new TemplatedEmail();
        $email
            ->to($send->getDestineeThirdParty()?->getEmail() ?? $send->getDestineeEmail())
            ->subject($title)
            ->htmlTemplate('@ChillMain/Workflow/workflow_send_external_email_to_destinee.html.twig')
            ->context([
                'send' => $send,
                'lang' => $message->lang,
            ]);

        $this->mailer->send($email);
    }
}
