<?php

declare(strict_types=1);

namespace App\Domain\Reputation;

/**
 * One entry in a Blocklist. Either a single IP (as canonical text) or a
 * CIDR (when the source is a manual subnet block). The text rendering
 * for the public endpoint is the `ipOrCidr` field as-is.
 *
 * Reasons:
 *   - `scored`: the entry comes from `ip_scores` and met at least one of the
 *     policy's category thresholds.
 *   - `manual`: the entry comes from `manual_blocks` (single or subnet) and
 *     the policy has `include_manual_blocks=true`.
 */
final class BlocklistEntry
{
    /**
     * @param list<string>             $categories     category slugs that matched (only for `scored`)
     * @param array<string, float>     $categoryScores per-matched-category score, keyed by slug;
     *                                                 empty for `manual`. Carried for the policy
     *                                                 preview's expiry estimate; not exposed in the
     *                                                 public blocklist JSON.
     */
    public function __construct(
        public readonly string $ipOrCidr,
        public readonly bool $isCidr,
        public readonly bool $isIpv4,
        public readonly array $categories,
        public readonly ?float $score,
        public readonly string $reason,
        public readonly array $categoryScores = [],
    ) {
    }

    /**
     * @return array<string, mixed>
     */
    public function toJsonArray(): array
    {
        return [
            'ip_or_cidr' => $this->ipOrCidr,
            'categories' => $this->categories,
            'score' => $this->score,
            'reason' => $this->reason,
        ];
    }
}
