<?php

declare(strict_types=1);

namespace App\Command;

use App\Config\ConfigSourceAuditProvider;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;

#[AsCommand(
    name: 'mto:agent:config:audit-source',
    description: 'Audit YAML-backed configuration versus remaining PHP defaults'
)]
final class ConfigSourceAuditCommand extends Command
{
    public function __construct(private readonly ConfigSourceAuditProvider $provider)
    {
        parent::__construct();
    }

    protected function configure(): void
    {
        $this
            ->addOption('json', null, InputOption::VALUE_NONE, 'Render the full audit result as JSON.')
            ->addOption('details', null, InputOption::VALUE_NONE, 'Render detailed fallback rows in the console summary.');
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $result = $this->provider->audit();

        if ((bool) $input->getOption('json')) {
            $json = json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
            $output->writeln(is_string($json) ? $json : '{}');

            return Command::SUCCESS;
        }

        $this->renderSummary(new SymfonyStyle($input, $output), $result, (bool) $input->getOption('details'));

        return Command::SUCCESS;
    }

    /**
     * @param array<string, mixed> $result
     */
    private function renderSummary(SymfonyStyle $io, array $result, bool $details): void
    {
        $io->title('RetrieX configuration source audit');

        $summary = is_array($result['summary'] ?? null) ? $result['summary'] : [];
        $io->definitionList(
            ['status' => (string) ($result['status'] ?? 'UNKNOWN')],
            ['yaml_parameter_paths' => (string) ($summary['yaml_parameter_paths'] ?? 0)],
            ['php_constants' => (string) ($summary['php_constants'] ?? 0)],
            ['php_only_constants' => (string) ($summary['php_only_constants'] ?? 0)],
            ['fallback_accessors' => (string) ($summary['fallback_accessors'] ?? 0)],
            ['fallback_accessors_with_yaml' => (string) ($summary['fallback_accessors_with_yaml'] ?? 0)],
            ['fallback_accessors_missing_yaml' => (string) ($summary['fallback_accessors_missing_yaml'] ?? 0)],
            ['constructor_defaults' => (string) ($summary['constructor_defaults'] ?? 0)],
            ['constructor_defaults_without_yaml_mapping' => (string) ($summary['constructor_defaults_without_yaml_mapping'] ?? 0)]
        );

        $warnings = is_array($result['warnings'] ?? null) ? $result['warnings'] : [];
        if ($warnings !== []) {
            $io->section('Warnings');
            foreach ($warnings as $warning) {
                $io->writeln('- ' . (string) $warning);
            }
        }

        if (!$details) {
            $io->note('Use --details for fallback rows or --json for the complete machine-readable audit.');
            return;
        }

        $fallbackRows = [];
        foreach (($result['fallback_accessors'] ?? []) as $item) {
            if (!is_array($item)) {
                continue;
            }

            $fallbackRows[] = [
                (string) ($item['class'] ?? ''),
                (string) ($item['line'] ?? ''),
                (string) ($item['key'] ?? ''),
                ((bool) ($item['yaml_present'] ?? false)) ? 'yes' : 'no',
                (string) ($item['source'] ?? ''),
            ];
        }

        if ($fallbackRows !== []) {
            $io->section('Fallback accessors');
            $io->table(['Class', 'Line', 'Key', 'YAML', 'Source'], $fallbackRows);
        }
    }
}
