<?php

declare(strict_types=1);

namespace App\Scolarite\Infrastructure\Console;

use App\Scolarite\Application\Command\EndReplacement\EndReplacementCommand;
use App\Scolarite\Application\Command\EndReplacement\EndReplacementHandler;
use App\Scolarite\Domain\Exception\RemplacementDejaTermineException;
use App\Scolarite\Domain\Repository\TeacherReplacementRepository;
use App\Shared\Domain\Clock;

use function count;

use Override;
use Psr\Log\LoggerInterface;

use function sprintf;

use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Throwable;

/**
 * Termine automatiquement les remplacements dont la date de fin est dépassée.
 *
 * CRON: 0 0 * * * php bin/console app:end-expired-replacements
 *
 * @see Story 2.9 - AC3: Fin automatique remplacement
 */
#[AsCommand(
    name: 'app:end-expired-replacements',
    description: 'Termine les remplacements dont la date de fin est dépassée',
)]
final class EndExpiredReplacementsCommand extends Command
{
    public function __construct(
        private readonly TeacherReplacementRepository $replacementRepository,
        private readonly EndReplacementHandler $endReplacementHandler,
        private readonly Clock $clock,
        private readonly LoggerInterface $logger,
    ) {
        parent::__construct();
    }

    #[Override]
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output);
        $io->title('Fin automatique des remplacements expirés');

        $expiredReplacements = $this->replacementRepository->findExpired($this->clock->now());

        if ($expiredReplacements === []) {
            $io->success('Aucun remplacement expiré à traiter.');

            return Command::SUCCESS;
        }

        $io->info(sprintf('%d remplacement(s) expiré(s) trouvé(s)', count($expiredReplacements)));

        $endedCount = 0;

        foreach ($expiredReplacements as $replacement) {
            try {
                ($this->endReplacementHandler)(new EndReplacementCommand(
                    replacementId: (string) $replacement->id,
                    tenantId: (string) $replacement->tenantId,
                ));

                $io->writeln(sprintf(
                    '  ✅ Remplacement %s terminé (remplaçant: %s)',
                    $replacement->id,
                    $replacement->replacementTeacherId,
                ));

                $this->logger->info('Remplacement terminé automatiquement', [
                    'replacement_id' => (string) $replacement->id,
                    'tenant_id' => (string) $replacement->tenantId,
                    'replaced_teacher_id' => (string) $replacement->replacedTeacherId,
                    'replacement_teacher_id' => (string) $replacement->replacementTeacherId,
                ]);

                ++$endedCount;
            } catch (RemplacementDejaTermineException $e) {
                $io->warning(sprintf(
                    '  ⚠ Remplacement %s déjà terminé, ignoré',
                    $replacement->id,
                ));

                $this->logger->info('Remplacement déjà terminé, ignoré lors du traitement automatique', [
                    'replacement_id' => (string) $replacement->id,
                ]);
            } catch (Throwable $e) {
                $io->error(sprintf(
                    'Erreur pour le remplacement %s : %s',
                    $replacement->id,
                    $e->getMessage(),
                ));

                $this->logger->error('Erreur lors de la terminaison automatique du remplacement', [
                    'replacement_id' => (string) $replacement->id,
                    'error' => $e->getMessage(),
                ]);
            }
        }

        $io->success(sprintf('%d remplacement(s) terminé(s) avec succès.', $endedCount));

        return Command::SUCCESS;
    }
}
