<?php

declare(strict_types=1);

namespace App\Command;

use App\Config\RetriexEffectiveConfigProvider;
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:dump-effective',
    description: 'Dump the effective RetrieX configuration inventory'
)]
final class ConfigDumpEffectiveCommand extends Command
{
    public function __construct(
        private readonly RetriexEffectiveConfigProvider $provider,
    ) {
        parent::__construct();
    }

    protected function configure(): void
    {
        $this->addOption('summary', null, InputOption::VALUE_NONE, 'Render a compact summary instead of JSON.');
    }

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

        if ((bool) $input->getOption('summary')) {
            $this->renderSummary(new SymfonyStyle($input, $output), $config);

            return Command::SUCCESS;
        }

        $json = json_encode($config, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
        $output->writeln(is_string($json) ? $json : '{}');

        return Command::SUCCESS;
    }

    /**
     * @param array<string, mixed> $config
     */
    private function renderSummary(SymfonyStyle $io, array $config): void
    {
        $io->title('RetrieX effective configuration');

        $runtime = $this->section($config, 'runtime');
        $model = $this->section($config, 'model_generation');
        $index = $this->section($config, 'index');
        $retrieval = $this->section($config, 'retrieval');
        $vector = $this->section($config, 'vector');
        $commerce = $this->section($config, 'commerce');
        $prompt = $this->section($config, 'prompt');
        $agent = $this->section($config, 'agent');
        $intent = $this->section($config, 'intent');
        $vocabulary = $this->section($config, 'vocabulary');
        $searchRepair = $this->section($config, 'search_repair');
        $commerceQuery = $this->section($config, 'commerce_query');
        $shopMatching = $this->section($config, 'shop_matching');
        $language = $this->section($config, 'language');
        $queryEnrichment = $this->section($config, 'query_enrichment');

        $io->section('Runtime');
        $io->definitionList(
            ['root' => (string) ($runtime['root'] ?? '')],
            ['knowledge_root' => (string) ($runtime['knowledge_root'] ?? '')],
            ['index_ndjson' => (string) ($runtime['index_ndjson'] ?? '')]
        );

        $io->section('Model');
        $io->definitionList(
            ['model_name' => (string) ($model['model_name'] ?? $model['default_model_name'] ?? '')],
            ['num_ctx' => (string) ($model['num_ctx'] ?? $model['default_num_ctx'] ?? '')],
            ['retrieval_max_chunks' => (string) ($model['retrieval_max_chunks'] ?? $model['default_retrieval_max_chunks'] ?? '')],
            ['retrieval_vector_top_k' => (string) ($model['retrieval_vector_top_k'] ?? $model['default_retrieval_vector_top_k'] ?? '')]
        );

        $io->section('Index');
        $io->definitionList(
            ['chunk_size' => (string) ($index['chunk_size'] ?? $index['fallback_chunk_size'] ?? '')],
            ['chunk_overlap' => (string) ($index['chunk_overlap'] ?? $index['fallback_chunk_overlap'] ?? '')],
            ['embedding_model' => (string) ($index['embedding_model'] ?? $index['fallback_embedding_model'] ?? '')],
            ['embedding_dimension' => (string) ($index['embedding_dimension'] ?? $index['fallback_embedding_dimension'] ?? '')]
        );

        $io->section('Retrieval');
        $io->definitionList(
            ['hard_max_chunks' => (string) ($retrieval['hard_max_chunks'] ?? '')],
            ['hard_max_vectork' => (string) ($retrieval['hard_max_vectork'] ?? '')],
            ['vector_score_threshold' => (string) ($retrieval['vector_score_threshold'] ?? '')],
            ['retrieval_vocabulary_lists' => (string) $this->countMapEntries($retrieval['vocabulary'] ?? [])]
        );

        $io->section('Vector');
        $io->definitionList(
            ['service_url' => (string) ($vector['service_url'] ?? '')],
            ['port' => (string) ($vector['port'] ?? '')],
            ['timeout' => (string) ($vector['timeout'] ?? '')]
        );

        $io->section('Commerce');
        $io->definitionList(
            ['enabled' => $this->formatBool($commerce['enabled'] ?? false)],
            ['max_shop_results' => (string) ($commerce['max_shop_results'] ?? '')],
            ['store_api_base_url' => (string) ($commerce['store_api_base_url'] ?? '')],
            ['commerce_query_lists' => (string) $this->countMapEntries($commerceQuery)],
            ['shop_matching_lists' => (string) $this->countMapEntries($shopMatching)],
            ['search_repair_lists' => (string) $this->countMapEntries($searchRepair)]
        );

        $io->section('Centralized YAML-backed configuration');
        $io->definitionList(
            ['vocabulary_classes' => (string) $this->countMapEntries($this->section($vocabulary, 'classes'))],
            ['vocabulary_views' => (string) $this->countMapEntries($this->section($vocabulary, 'views'))],
            ['intent_sections' => (string) $this->countMapEntries($intent)],
            ['prompt_rule_groups' => (string) $this->countMapEntries($this->section($prompt, 'rules'))],
            ['agent_message_groups' => (string) $this->countMapEntries($this->section($agent, 'messages'))],
            ['stopwords' => (string) $this->countListEntries($language['stopwords'] ?? [])],
            ['query_enrichment_rules' => (string) $this->countMapEntries($queryEnrichment['rules'] ?? [])]
        );
    }

    /**
     * @param array<string, mixed> $data
     * @return array<string, mixed>
     */
    private function section(array $data, string $key): array
    {
        return isset($data[$key]) && is_array($data[$key]) ? $data[$key] : [];
    }

    private function formatBool(mixed $value): string
    {
        return filter_var($value, FILTER_VALIDATE_BOOLEAN) ? 'yes' : 'no';
    }

    private function countMapEntries(mixed $value): int
    {
        return is_array($value) ? count($value) : 0;
    }

    private function countListEntries(mixed $value): int
    {
        return is_array($value) ? count($value) : 0;
    }
}
