<?php

namespace KupShop\KupShopBundle\Command;

use KupShop\KupShopBundle\Event\CronEvent;
use KupShop\KupShopBundle\Util\Event\LoggingEventDispatcher;
use KupShop\KupShopBundle\Util\Logging\SentryLogger;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

#[AsCommand(name: 'kupshop:run_cron', description: 'Run cron job')]
class RunCronCommand extends Command
{
    /** @var LoggingEventDispatcher */
    private $eventDispatcher;

    /** @var SentryLogger */
    private $sentryLogger;

    /**
     * @required
     */
    public function setLoggingEventDispatcher(LoggingEventDispatcher $eventDispatcher): void
    {
        $this->eventDispatcher = $eventDispatcher;
    }

    /**
     * @required
     */
    public function setSentryLogger(SentryLogger $sentryLogger): void
    {
        $this->sentryLogger = $sentryLogger;
    }

    protected function configure()
    {
        $this
            ->addArgument('type', InputArgument::OPTIONAL, 'Type of cron to run. One of [FREQUENT, NORMAL, EXPENSIVE]', 'NORMAL')
            ->addOption('method', 'm', InputOption::VALUE_OPTIONAL, 'Call specific cron method - write just method, f.e.: "-m activatePoints"', false);
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        try {
            $event = new CronEvent($input->getArgument('type'));
            $eventName = constant('KupShop\KupShopBundle\Event\CronEvent::RUN_'.$input->getArgument('type'));

            if ($input->hasOption('method')) {
                $method = $input->getOption('method');

                if ($method === null) {
                    // List all available handlers and exit
                    $table = new Table($output);
                    $table
                        ->setHeaders(['Handler']);

                    foreach ($this->eventDispatcher->getListeners($eventName) as $listener) {
                        $table->addRow([sprintf('%s::%s', get_class($listener[0]), $listener[1])]);
                    }

                    $table->render();

                    return 0;
                }

                $this->eventDispatcher->setSpecificMethod($input->getOption('method'));
            }

            $this->eventDispatcher->dispatch(
                $event,
                $eventName,
            );
        } catch (\Throwable $e) {
            $this->sentryLogger->setChannel(SentryLogger::CHANNEL_CRON)->captureException($e);
            throw $e;
        }

        return 0;
    }
}
