<?php

declare(strict_types=1);

namespace Autogedal\FeedMonitor\Console\Command;

use Autogedal\FeedMonitor\Model\JobRegistry;
use Autogedal\FeedMonitor\Model\MonitorKey;
use Autogedal\FeedMonitor\Model\Problem;
use Autogedal\FeedMonitor\Model\RunRepository;
use Autogedal\FeedMonitor\Model\StateRepository;
use Magento\Cron\Model\ConfigInterface as CronConfig;
use Magento\Framework\Console\Cli;
use Magento\Framework\Stdlib\DateTime\TimezoneInterface;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class StatusCommand extends Command
{
    public function __construct(
        private readonly JobRegistry $jobs,
        private readonly RunRepository $runs,
        private readonly StateRepository $states,
        private readonly TimezoneInterface $timezone,
        private readonly CronConfig $cronConfig
    ) {
        parent::__construct();
    }

    protected function configure(): void
    {
        $this->setName('autogedal:feed-monitor:status')
            ->setDescription('Feed monitor: last run and open alert of every monitored job');
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $table = new Table($output);
        $table->setHeaders(['Job', 'Ultima rulare', 'Status', 'Problema', 'Citite', 'Actualizate', 'Alerta']);
        foreach (array_merge($this->jobs->getMonitorKeys(), [MonitorKey::MAGENTO_CRON]) as $key) {
            [$jobCode, $feedCode] = MonitorKey::split($key);
            $run = $key === MonitorKey::MAGENTO_CRON ? null : $this->runs->getLastRun($jobCode, $feedCode);
            $state = $this->states->get($key);
            $table->addRow([
                $key,
                $run ? $this->local((string)$run['started_at']) : '-',
                $run['status'] ?? '-',
                $run && $run['problem'] ? Problem::label((string)$run['problem']) : '',
                $run['items_read'] ?? '',
                $run['items_updated'] ?? '',
                $state && (int)$state['alert_open'] ? 'DA: ' . Problem::label((string)$state['problem']) : '',
            ]);
        }
        $table->render();

        // a job code mistyped in di.xml would be reported as "not running" forever
        $scheduled = [];
        foreach ($this->cronConfig->getJobs() as $groupJobs) {
            $scheduled += $groupJobs;
        }
        $missing = array_diff($this->jobs->getJobCodes(JobRegistry::SOURCE_CUSTOM), array_keys($scheduled));
        if ($missing) {
            $output->writeln('<error>Joburi urmarite care nu exista in niciun crontab.xml: ' . implode(', ', $missing) . '</error>');
            return Cli::RETURN_FAILURE;
        }

        return Cli::RETURN_SUCCESS;
    }

    private function local(string $utc): string
    {
        return $this->timezone->date(new \DateTime($utc, new \DateTimeZone('UTC')))->format('d.m.Y H:i');
    }
}
