<?php

declare(strict_types=1);

namespace Plugin\tnt_mcp\src\Mcp\Log;

/**
 * One `read_logs` answer: the aggregation header first, the entries second.
 *
 * The order is the product. `totalMatching` + `byLevel` + `byChannel` + `topMessages` are computed
 * over the whole window, not over the returned page, so an LLM can answer "what is wrong with this
 * shop" from the header alone and only page into `entries` when it needs an example. `byLevel` is
 * null — not empty — for a source that genuinely has no severity, so the caller can tell "no
 * errors" apart from "this source does not know what an error is".
 */
final class LogPage
{
    /**
     * @param array<string,int>|null                                                    $byLevel
     * @param array<string,int>|null                                                    $byChannel
     * @param list<array{count:int,sample:string,firstSeen:string,lastSeen:string}>     $topMessages
     * @param list<array<string,mixed>>                                                 $entries
     * @param list<string>                                                              $notes
     * @param array<string,int>|null                                                    $byAdmin
     */
    public function __construct(
        public readonly int $totalMatching,
        public readonly ?array $byLevel,
        public readonly ?array $byChannel,
        public readonly array $topMessages,
        public readonly array $entries,
        public readonly ?string $nextCursor,
        public readonly array $notes,
        public readonly bool $available = true,
        public readonly ?string $reason = null,
        public readonly ?array $byAdmin = null,
    ) {
    }

    /** The "this source is switched off in the shop's config" answer — not an error. */
    public static function unavailable(string $reason, string $note): self
    {
        return new self(0, null, null, [], [], null, [$note], false, $reason);
    }
}
