<?php

namespace App\Commands;

use App\Commands\Concerns\InteractsWithPijul;
use JsonException;
use LaravelZero\Framework\Commands\Command;

class PijulListIntentTagsCommand extends Command
{
    use InteractsWithPijul;

    /**
     * @var string
     */
    protected $signature = 'pijul:list-intent-tags
                            {--limit= : Number of recent log entries to scan}
                            {--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 = 'List unique intent tags from pijul log messages';

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

    /**
     * @throws JsonException
     */
    public function handle(): int
    {
        foreach ($this->resolveTags(
            limit: $this->option('limit'),
            repository: $this->option('repository'),
            channel: $this->option('channel'),
            noPrompt: (bool) $this->option('no-prompt'),
        ) as $tag) {
            $this->line($tag);
        }

        return self::SUCCESS;
    }

    /**
     * @return list<string>
     *
     * @throws JsonException
     */
    public function resolveTags(
        ?string $limit = null,
        ?string $repository = null,
        ?string $channel = null,
        bool $noPrompt = false,
    ): array {
        $arguments = ['log', '--output-format', 'json'];

        if ($limit !== null && $limit !== '') {
            $arguments[] = '--limit';
            $arguments[] = $limit;
        }

        if ($repository !== null && $repository !== '') {
            $arguments[] = '--repository';
            $arguments[] = $repository;
        }

        if ($channel !== null && $channel !== '') {
            $arguments[] = '--channel';
            $arguments[] = $channel;
        }

        if ($noPrompt) {
            $arguments[] = '--no-prompt';
        }

        $changes = json_decode(
            $this->runPijul($arguments)->output(),
            true,
            512,
            JSON_THROW_ON_ERROR,
        );

        $tags = [];

        foreach ($changes as $change) {
            $message = $change['message'] ?? null;

            if (! is_string($message) || preg_match('/^([A-Za-z0-9_-]+\([^)]*\))/', $message, $matches) !== 1) {
                continue;
            }

            $tags[$matches[1]] = true;
        }

        return array_keys($tags);
    }
}