<?php declare(strict_types = 1);

namespace idoit\Module\Synetics_flows\Console\Command;

use DateTime;
use idoit\Console\Command\AbstractCommand;
use idoit\Module\SyneticsFlows\Automation\Action\ExecutionResult\DebugResult;
use idoit\Module\SyneticsFlows\Automation\Action\ExecutionResult\ErrorExecutionInterface;
use idoit\Module\SyneticsFlows\Automation\Execution;
use idoit\Module\SyneticsFlows\Automation\TriggerFacade;
use isys_application;
use isys_module_manager;
use isys_module_synetics_flows;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\ProgressBar;
use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class PerformCommand extends AbstractCommand
{
    const NAME = 'flows:perform';

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $language = isys_application::instance()->container->get('language');
        isys_application::instance()->container->get('moduleManager')->processAddonLicenses();

        if (!isys_module_manager::instance()->is_active('synetics_flows')) {
            $output->writeln('Flows add-on is not active');

            return Command::FAILURE;
        }

        if (!isys_module_manager::instance()->is_installed('synetics_flows')) {
            $output->writeln('Flows add-on is not installed');

            return Command::FAILURE;
        }
        $dao = TriggerFacade::getExecutionDao();
        $service = TriggerFacade::getService();
        $now = (new DateTime('now'))->format(DateTime::ATOM);
        $executions = $dao->getData('AND execution.time < \'' . $now . '\' AND execution.status in (\'waiting\')');

        if (!count($executions)) {
            return Command::SUCCESS;
        }

        $table = new Table($output);
        $table->setHeaders([
            'ID',
            'Invocation',
            'Execution',
            'Duration',
            'Result type',
            'Result',
        ]);
        $progressBar = new ProgressBar($output, count($executions));

        foreach ($executions as $execution) {
            $progressBar->advance();
            if (!$execution instanceof Execution) {
                continue;
            }
            $start = microtime(true);
            $result = $service->perform($execution->getId());
            if (!$result) {
                continue;
            }
            $duration = microtime(true) - $start;
            $type = 'Success';
            if ($result instanceof ErrorExecutionInterface) {
                $type = 'Error';
            }
            if ($result instanceof DebugResult) {
                $type = 'Test mode';
            }
            $table->addRow([
                $execution->getId(),
                $execution->getInvocation(),
                $execution->getExecution(),
                round($duration * 1000) . 'ms',
                $type,
                $result,
            ]);
        }
        $progressBar->finish();
        $output->writeln('');
        $table->render();
        return Command::SUCCESS;
    }

    public function getCommandName(): string
    {
        return self::NAME;
    }

    public function getCommandDescription(): string
    {
        return 'Perform executions';
    }

    public function getCommandDefinition(): InputDefinition
    {
        return new InputDefinition();
    }

    public function isConfigurable(): bool
    {
        return true;
    }

    public function getCommandUsages(): array
    {
        return [];
    }
}
