#!/usr/bin/php
<?php
define('EXIT_WRONG_USAGE', 127);
define('EXIT_SERVICES_NON_INSTANTIABLE', 1);

if (!file_exists('src/Kernel.php')) {
    die("Please run this command from your Symfony application root.");
}

require 'config/bootstrap.php';

use Symfony\Component\Console\Exception\RuntimeException;
use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\ConsoleOutput;
use Symfony\Component\DependencyInjection\ContainerInterface;

$ignoreServiceIds = [
    'onelogin_auth', // execute a database request in the constructor in EE
];

$inputDefinition = new InputDefinition(array(
  new InputOption('verbose', 'v', InputOption::VALUE_NONE, 'Verbose mode: list all service ids we tried to instantiate.'. false)
));

$output = new ConsoleOutput();
$input = new ArgvInput($argv);

try {
    $input->bind($inputDefinition);
    $input->validate();
} catch (RuntimeException $e) {
    $output->writeln(
        sprintf('<error>Wrong usage: %s</error>', $e->getMessage())
    );

    exit (EXIT_WRONG_USAGE);
}

$verbosity = $input->getOption('verbose') ? ConsoleOutput::VERBOSITY_VERBOSE : ConsoleOutput::VERBOSITY_NORMAL;
$output->setVerbosity($verbosity);

$kernel = new Kernel('dev', false);
$kernel->boot();

$exitStatus = checkServicesInstantiability($kernel->getContainer(), $output, $ignoreServiceIds);

exit ($exitStatus);

function checkServicesInstantiability(ContainerInterface $container, ConsoleOutput $output, array $ignoreServiceIds): int
{
    $serviceIds = $container->getServiceIds();

    $nonInstantiableServices = [];

    foreach ($serviceIds as $serviceId) {

        if (in_array($serviceId, $ignoreServiceIds)) {
            continue;
        }

        if ($output->isVerbose()) {
            $output->writeln("Getting $serviceId");
        }

        try {
            $service = $container->get($serviceId);
            if ($service instanceof \ProxyManager\Proxy\VirtualProxyInterface) {
                $service->initializeProxy();
            }
        } catch (\Throwable $t) {
            $nonInstantiableServices[$serviceId] = ["error_type" => get_class($t), "error_message" => $t->getMessage()];
        }
    }

    if (0 === count($nonInstantiableServices)) {
        $output->writeln(
            sprintf(
                "<info>All %s services are instantiable.</info>",
                count($serviceIds)
            )
        );

        return 0;
    } else {
        $output->writeln(
            sprintf(
                "<comment>Found %s non instantiable services on a total of %s.</comment>",
                count($nonInstantiableServices),
                count($serviceIds),
            )
        );
        foreach ($nonInstantiableServices as $nonInstantiableServiceId => $nonInstantiableServiceReason) {
            $output->writeln(
                sprintf('<error>%s</error>',$nonInstantiableServiceId)
            );
            $output->write($nonInstantiableServiceReason['error_type']);
            $output->write(": ");
            $output->writeln($nonInstantiableServiceReason['error_message']);
            $output->writeln("------");
        }

        return EXIT_SERVICES_NON_INSTANTIABLE;
    }
}

