<?php

declare(strict_types=1);

namespace App\Scolarite\Infrastructure\Messaging;

use App\Administration\Domain\Model\User\Role;
use App\Administration\Domain\Model\User\UserId;
use App\Administration\Domain\Repository\UserRepository;
use App\Scolarite\Domain\Event\ExceptionDevoirDemandee;
use App\Scolarite\Domain\Repository\HomeworkRepository;

use function array_filter;
use function count;

use Psr\Log\LoggerInterface;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Messenger\Attribute\AsMessageHandler;
use Symfony\Component\Mime\Email;
use Throwable;
use Twig\Environment;

/**
 * Notifie la direction lorsqu'un enseignant demande une exception aux règles de devoirs.
 */
#[AsMessageHandler(bus: 'event.bus')]
final readonly class OnExceptionDevoirDemandeeHandler
{
    public function __construct(
        private HomeworkRepository $homeworkRepository,
        private UserRepository $userRepository,
        private MailerInterface $mailer,
        private Environment $twig,
        private LoggerInterface $logger,
        private string $fromEmail = 'noreply@classeo.fr',
    ) {
    }

    public function __invoke(ExceptionDevoirDemandee $event): void
    {
        $homework = $this->homeworkRepository->findById($event->homeworkId, $event->tenantId);

        if ($homework === null) {
            $this->logger->warning('Exception devoir : homework introuvable', [
                'homework_id' => (string) $event->homeworkId,
                'exception_id' => (string) $event->exceptionId,
            ]);

            return;
        }

        $teacher = $this->userRepository->findById(UserId::fromString((string) $event->createdBy));

        $allUsers = $this->userRepository->findAllByTenant($event->tenantId);
        $directors = array_filter(
            $allUsers,
            static fn ($user) => $user->aLeRole(Role::ADMIN),
        );

        if (count($directors) === 0) {
            $this->logger->info('Exception devoir demandée — aucun directeur à notifier', [
                'tenant_id' => (string) $event->tenantId,
                'homework_id' => (string) $event->homeworkId,
            ]);

            return;
        }

        $teacherName = $teacher !== null ? $teacher->firstName . ' ' . $teacher->lastName : 'Enseignant inconnu';

        $html = $this->twig->render('emails/homework_exception_notification.html.twig', [
            'teacherName' => $teacherName,
            'homeworkTitle' => $homework->title,
            'ruleTypes' => $event->ruleTypes,
            'justification' => $event->justification,
            'dueDate' => $homework->dueDate->format('d/m/Y'),
        ]);

        $sent = 0;

        foreach ($directors as $director) {
            try {
                $email = (new Email())
                    ->from($this->fromEmail)
                    ->to((string) $director->email)
                    ->subject('Exception aux règles de devoirs — ' . $homework->title)
                    ->html($html);

                $this->mailer->send($email);
                ++$sent;
            } catch (Throwable $e) {
                $this->logger->warning('Échec envoi notification exception devoir', [
                    'director_email' => (string) $director->email,
                    'error' => $e->getMessage(),
                ]);
            }
        }

        $this->logger->info('Notifications exception devoir envoyées', [
            'tenant_id' => (string) $event->tenantId,
            'homework_id' => (string) $event->homeworkId,
            'exception_id' => (string) $event->exceptionId,
            'emails_sent' => $sent,
            'directors_total' => count($directors),
        ]);
    }
}
