<?php

declare(strict_types=1);

namespace app\vendor\apexl\io\src\Io\modules\system\commands;

use apexl\Io\modules\system\services\RouteDebugHelper;
use Closure;
use ReflectionFunction;
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\Output\OutputInterface;

#[AsCommand(name: 'routes:dump', description: 'Dumps registered routes file to console')]
class DumpRoutesCommand extends DaedalusCommand
{
    public function __construct(private readonly RouteDebugHelper $routeDebugHelper, ?string $name = null)
    {
        parent::__construct($name);
    }

    protected function configure(): void
    {
        parent::configure();

        $this->addOption('output', 'o', InputArgument::OPTIONAL, 'Output format (json, php)', 'table');
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {

        $data = $this->routeDebugHelper->routes();

        $outputDisplay = $input->getOption('output');

        if ($outputDisplay === 'table') {
            $rows = [];
            foreach ($data as $module => $moduleRoutes) {
                $rows = [
                    ...$rows,
                    ...array_map(
                        function (mixed $value) use ($module): array {
                            unset($value['args']['moduleName']);

                            if (is_array($value['callable'])) {
                                $value['callable'] = json_encode($value['callable']);
                            } elseif ($value['callable'] instanceof Closure) {
                                $reflectionClosure = new ReflectionFunction($value['callable']);
                                $value['callable'] = $reflectionClosure->name;
                            } elseif (is_object($value['callable']) && !method_exists(
                                    $value['callable'],
                                    '__toString'
                                )) {
                                $value['callable'] = get_class($value['callable']);
                            }

                            return [
                                $module,
                                $value['name'],
                                $value['verb'],
                                $value['pattern'],
                                $value['callable'],
                                json_encode($value['args']),
                            ];
                        },
                        $moduleRoutes,
                    )
                ];
            }

            $table = new Table($output);
            $table
                ->setHeaderTitle($key ?? 'Config')
                ->setHeaders([
                    'Module',
                    'Name',
                    'Verb',
                    'Pattern',
                    'Callable',
                    'Args',
                ])
                ->setRows($rows);
            $table->render();
        } else {
            $config = match ($input->getOption('output')) {
                'json' => json_encode($data, JSON_PRETTY_PRINT),
                default => print_r($data, true),
            };

            $output->write($config);
        }

        return Command::SUCCESS;
    }
}
