<?php

namespace App\Commands;

use App\Service\Dolibarr\DolibarrSyncService;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Command\LockableTrait;
use Symfony\Component\Console\Helper\ProgressBar;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

#[AsCommand(
    name: 'ot:dolibarr-sync',
    description: 'Push the latest data from the Opentalent DB to dolibarr'
)]
class DolibarrSyncCommand extends Command
{
    use LockableTrait;

    /**
     * How many operations are shown each time the preview choice is made
     */
    const PREVIEW_CHUNK = 20;

    public function __construct(
        private DolibarrSyncService $dolibarrSyncService
    ) {
        parent::__construct();
    }

    protected function configure(): void
    {
        $this->addOption(
            'preview',
            'p',
            InputOption::VALUE_NONE,
            'Only preview the sync operations instead of executing it'
        );
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        if (!$this->lock()) {
            $output->writeln('The command is already running in another process.');
            return Command::SUCCESS;
        }

        $output->writeln("Start the synchronization");
        $t0 = microtime(true);
        $output->writeln("Scanning...");

        $progressBar = new ProgressBar($output, 0);
        $progressCallback = function($i, $total) use ($progressBar) {
            if (!$progressBar->getMaxSteps() !== $total) {
                $progressBar->setMaxSteps($total);
            }
            $progressBar->setProgress($i);
        };

        $operations = $this->dolibarrSyncService->scan($progressCallback);

        $t1 = microtime(true);
        $output->writeln("Scan lasted " . ($t1 - $t0) . " sec.");

        $output->writeln(count($operations) . " operations to be executed");

        if ($input->getOption('preview')) {
            $output->writeln("-- Preview --");
            foreach ($operations as $i => $iValue) {
                $output->writeln($i . '. ' . $iValue->getLabel());
                foreach ($iValue->getChangeLog() as $message) {
                    $output->writeln('   ' . $message);
                }
            }
        } else {
            $t0 = microtime(true);
            $output->writeln("Executing...");

            $operations = $this->dolibarrSyncService->execute($operations, $progressCallback);

            $successes = count(array_filter($operations, function ($o) { return $o->getStatus() === $o::STATUS_DONE; } ));
            $errors = count(array_filter($operations, function ($o) { return $o->getStatus() === $o::STATUS_ERROR; } ));
            $output->writeln($successes . " operations successfully executed");
            $output->writeln($errors . " errors");

            $t1 = microtime(true);
            $output->writeln("Execution lasted " . ($t1 - $t0) . " sec.");
        }

        return Command::SUCCESS;
    }
}
