<?php

declare(strict_types=1);

namespace App\Command;

use App\Commerce\SearchRepairService;
use App\Commerce\ShopSearchService;
use App\Intent\CommerceIntentLite;
use App\Knowledge\Retrieval\RetrieverInterface;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

#[AsCommand(name: 'mto:agent:test:shop-search')]
final class TestShopSearchCommand extends Command
{
    public function __construct(
        private readonly ShopSearchService $shopSearchService,
        private readonly SearchRepairService $searchRepairService,
        private readonly RetrieverInterface $retriever,
    ) {
        parent::__construct();
    }

    protected function configure(): void
    {
        $this
            ->addArgument(
                'query',
                InputArgument::OPTIONAL,
                'Die zu testende Suchanfrage',
                'zeige mir testomat modelle wasserhärte unter 5000 euro'
            )
            ->addOption(
                'intent',
                null,
                InputOption::VALUE_OPTIONAL,
                'Commerce intent',
                CommerceIntentLite::ADVISORY_PRODUCT_SEARCH
            )
            ->addOption(
                'history',
                null,
                InputOption::VALUE_OPTIONAL,
                'Optionaler Commerce-History-Kontext',
                ''
            )
            ->addOption(
                'repair',
                null,
                InputOption::VALUE_NONE,
                'Aktiviert zusätzlich den Search-Repair-Test'
            );
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $query = trim((string) $input->getArgument('query'));
        $intent = trim((string) $input->getOption('intent'));
        $history = trim((string) $input->getOption('history'));
        $useRepair = (bool) $input->getOption('repair');

        $output->writeln('<info>Test query:</info> ' . $query);
        $output->writeln('<info>Intent:</info> ' . $intent);
        $output->writeln('<info>Repair:</info> ' . ($useRepair ? 'ja' : 'nein'));

        if ($history !== '') {
            $output->writeln('<info>History:</info> ' . $history);
        }

        $output->writeln('');

        $primaryResults = $this->shopSearchService->search($query, $intent, $history);

        $output->writeln('<comment>Primärsuche</comment>');
        $this->renderResults($output, $primaryResults);

        if (!$useRepair) {
            return Command::SUCCESS;
        }

        $knowledgeChunks = $this->retriever->retrieve($query);

        $repairPayload = $this->searchRepairService->repair(
            prompt: $query,
            commerceIntent: $intent,
            commerceHistoryContext: $history,
            primaryQuery: $query,
            primaryShopResults: $primaryResults,
            knowledgeChunks: $knowledgeChunks
        );

        $output->writeln('');
        $output->writeln('<comment>Repair-Auswertung</comment>');
        $output->writeln('  Used repair: ' . ($repairPayload['usedRepair'] ? 'ja' : 'nein'));
        $output->writeln('  Repair queries: ' . (
            $repairPayload['repairQueries'] !== []
                ? implode(' | ', $repairPayload['repairQueries'])
                : '-'
            ));
        $output->writeln('');

        $output->writeln('<comment>Finale Ergebnisse nach Repair/Merge</comment>');
        $this->renderResults($output, $repairPayload['results']);

        return Command::SUCCESS;
    }

    /**
     * @param array<int, object> $results
     */
    private function renderResults(OutputInterface $output, array $results): void
    {
        if ($results === []) {
            $output->writeln('Keine Shop-Ergebnisse gefunden.');

            return;
        }

        foreach ($results as $index => $result) {
            $n = $index + 1;

            $output->writeln(sprintf('[%d] %s', $n, $result->name));
            $output->writeln('  ID: ' . $result->id);
            $output->writeln('  Produktnummer: ' . ($result->productNumber ?? '-'));
            $output->writeln('  Hersteller: ' . ($result->manufacturer ?? '-'));
            $output->writeln('  Preis: ' . ($result->price ?? '-'));
            $output->writeln('  Verfügbar: ' . ($result->available === null ? '-' : ($result->available ? 'ja' : 'nein')));
            $output->writeln('  URL: ' . ($result->url ?? '-'));
            $output->writeln('  Description: ' . ($result->description ?? '-'));

            if (property_exists($result, 'matchScore')) {
                $output->writeln('  MatchScore: ' . (($result->matchScore ?? null) !== null ? (string) $result->matchScore : '-'));
            }

            if (property_exists($result, 'matchSource')) {
                $output->writeln('  MatchSource: ' . ($result->matchSource ?? '-'));
            }

            if (property_exists($result, 'matchedQueries') && is_array($result->matchedQueries) && $result->matchedQueries !== []) {
                $output->writeln('  MatchedQueries: ' . implode(' | ', $result->matchedQueries));
            }

            if (is_array($result->highlights) && $result->highlights !== []) {
                $output->writeln('  Highlights:');
                foreach ($result->highlights as $highlight) {
                    $output->writeln('    - ' . $highlight);
                }
            }

            $output->writeln('');
        }
    }
}