<?php

use App\Prompts\LiveSuggestPrompt;
use App\Prompts\Renderers\LiveSuggestPromptRenderer;
use Illuminate\Process\PendingProcess;
use Illuminate\Support\Facades\Process;
use Laravel\Prompts\Key;

it('searches intent tags using the list command logic and passes through the limit', function () {
    Process::fake(function (PendingProcess $process) {
        return match ($process->command) {
            ['pijul', 'log', '--output-format', 'json', '--limit', '50'] => Process::result(json_encode([
                ['message' => 'feat(pijul-qol): first'],
                ['message' => 'feat(pijul-qol:move-to-zero): second'],
                ['message' => 'fix(cli): third'],
            ], JSON_THROW_ON_ERROR)),
            default => Process::result('', 'Unexpected command.', 1),
        };
    });

    $this->artisan('pijul:search-intent-tags', [
        'query' => 'zero',
        '--limit' => '50',
    ])
        ->expectsOutput('feat(pijul-qol:move-to-zero)')
        ->assertExitCode(0);

    Process::assertRanTimes(fn (PendingProcess $process) => $process->command === [
        'pijul',
        'log',
        '--output-format',
        'json',
        '--limit',
        '50',
    ], 1);
});

it('can search for an exact tag match', function () {
    Process::fake(function (PendingProcess $process) {
        return match ($process->command) {
            ['pijul', 'log', '--output-format', 'json'] => Process::result(json_encode([
                ['message' => 'feat(pijul-qol): first'],
                ['message' => 'feat(pijul-qol:move-to-zero): second'],
            ], JSON_THROW_ON_ERROR)),
            default => Process::result('', 'Unexpected command.', 1),
        };
    });

    $this->artisan('pijul:search-intent-tags', [
        'query' => 'feat(pijul-qol)',
        '--exact' => true,
    ])
        ->expectsOutput('feat(pijul-qol)')
        ->assertExitCode(0);
});

it('shows live suggestions starting from all tags when prompted for a query', function () {
    Process::fake(function (PendingProcess $process) {
        return match ($process->command) {
            ['pijul', 'log', '--output-format', 'json'] => Process::result(json_encode([
                ['message' => 'feat(pijul-qol): first'],
                ['message' => 'feat(pijul-qol:move-to-zero): second'],
                ['message' => 'fix(cli): third'],
            ], JSON_THROW_ON_ERROR)),
            default => Process::result('', 'Unexpected command.', 1),
        };
    });

    LiveSuggestPrompt::fake(['z', 'e', 'r', 'o', Key::ENTER]);

    $this->artisan('pijul:search-intent-tags')
        ->expectsOutput('feat(pijul-qol:move-to-zero)')
        ->assertExitCode(0);
});

it('renders initial live suggestions before any query is typed', function () {
    LiveSuggestPrompt::fake();

    $prompt = new LiveSuggestPrompt(
        label: 'Search query',
        options: fn (string $value): array => $value === ''
            ? ['feat(pijul-qol)', 'feat(pijul-qol:move-to-zero)', 'fix(cli)']
            : ['fix(cli)'],
        placeholder: 'Type to filter intent tags...',
        scroll: 10,
        required: 'Please provide a search query.',
    );

    $output = (new LiveSuggestPromptRenderer($prompt))($prompt);

    expect(preg_replace("/\e\[[0-9;?]*[A-Za-z]/", '', $output))
        ->toContain('feat(pijul-qol)')
        ->toContain('fix(cli)');
});

it('returns all tags when the live filter has no input yet', function () {
    $command = app(App\Commands\PijulSearchIntentTagsCommand::class);

    $method = new ReflectionMethod($command, 'suggestedTags');
    $method->setAccessible(true);

    expect($method->invoke($command, [
        'feat(pijul-qol)',
        'feat(pijul-qol:move-to-zero)',
        'fix(cli)',
    ], ''))->toBe([
        'feat(pijul-qol)',
        'feat(pijul-qol:move-to-zero)',
        'fix(cli)',
    ]);
});