<?php

namespace App\Commands;

use App\Prompts\LiveSuggestPrompt;
use LaravelZero\Framework\Commands\Command;

class PijulSearchIntentTagsCommand extends Command
{
    private const LIVE_RESULTS_SCROLL = 10;

    /**
     * @var string
     */
    protected $signature = 'pijul:search-intent-tags
                            {query? : Text to search for in intent tags}
                            {--limit= : Number of recent log entries to scan}
                            {--exact : Match the whole tag instead of a substring}
                            {--repository= : Work with the repository at PATH}
                            {--channel= : Work with CHANNEL instead of the current channel}
                            {--no-prompt : Abort rather than prompt for input}';

    /**
     * @var string
     */
    protected $description = 'Search intent tags extracted from pijul log messages';

    /**
     * @var array<int, string>
     */
    protected $aliases = ['pijul-search-intent-tags'];

    public function handle(PijulListIntentTagsCommand $listIntentTags): int
    {
        $query = trim((string) ($this->argument('query') ?? ''));
        $tags = $listIntentTags->resolveTags(
            limit: $this->option('limit'),
            repository: $this->option('repository'),
            channel: $this->option('channel'),
            noPrompt: (bool) $this->option('no-prompt'),
        );

        if ($query === '' && $this->input->isInteractive()) {
            $query = trim((string) (new LiveSuggestPrompt(
                label: 'Search query',
                options: fn (string $value): array => $this->suggestedTags($tags, $value),
                placeholder: 'Type to filter intent tags...',
                scroll: self::LIVE_RESULTS_SCROLL,
                required: 'Please provide a search query.',
                hint: 'Results update on each keypress. Use arrows to scroll, then press Enter.',
            ))->prompt());
        }

        if ($query === '') {
            $this->error('Please provide a search query.');

            return self::FAILURE;
        }

        $matches = array_values(array_filter(
            $tags,
            fn (string $tag): bool => $this->matchesQuery($tag, $query),
        ));

        if ($matches === []) {
            $this->warn('No matching intent tags found.');

            return self::SUCCESS;
        }

        foreach ($matches as $match) {
            $this->line($match);
        }

        return self::SUCCESS;
    }

    /**
     * @param  list<string>  $tags
     * @return list<string>
     */
    private function suggestedTags(array $tags, string $query): array
    {
        $query = trim($query);

        if ($query === '') {
            return array_values($tags);
        }

        return array_values(array_filter(
            $tags,
            fn (string $tag): bool => str_contains(strtolower($tag), strtolower($query)),
        ));
    }

    private function matchesQuery(string $tag, string $query): bool
    {
        if ($this->option('exact')) {
            return strcasecmp($tag, $query) === 0;
        }

        return str_contains(strtolower($tag), strtolower($query));
    }
}