<?php

namespace App\Shared\Event\Command;

use App\Shared\Event\Entity\DomainEventLog;
use App\Shared\Event\Repository\DomainEventLogRepository;
use App\Shared\Event\Service\OutboxPublisher;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;

/**
 * اجرای دستیِ انتشار صندوق خروجی.
 *
 * منطقش در `OutboxPublisher` است چون زمان‌بند هم همان را هر دقیقه صدا می‌زند؛ این دستور
 * برای وقتی می‌ماند که صف عقب افتاده و باید همین حالا تخلیه شود.
 */
#[AsCommand(name: 'app:events:publish', description: 'Publish pending domain events from the outbox.')]
class PublishDomainEventsCommand extends Command
{
    public function __construct(
        private readonly OutboxPublisher          $publisher,
        private readonly DomainEventLogRepository $events,
    ) {
        parent::__construct();
    }

    protected function configure(): void
    {
        $this->addOption('limit', null, InputOption::VALUE_REQUIRED, 'How many events to publish per run', '100');
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io     = new SymfonyStyle($input, $output);
        $result = $this->publisher->publish((int) $input->getOption('limit'));

        $io->success(sprintf('%d رویداد منتشر شد، %d ناموفق.', $result['published'], $result['failed']));

        return Command::SUCCESS;
    }

    /** @return DomainEventLog[] */
    public function pending(int $limit = 100): array
    {
        return $this->events->findPending($limit);
    }
}
