<?php

declare(strict_types=1);

namespace Plugin\tnt_mcp\src\Mcp\Action;

/**
 * A rule that binds several fields together — parallel arrays of equal length, a flag whose amount
 * is only read when it is on, or the set of fields that must ALL be present or nothing is written
 * and no error is raised. Structured rather than prose because the caller is meant to validate
 * against it before spending an invocation, not just read it.
 *
 * `fields` is free text: it names pairs such as `bis[]/preis[]`, so it is deliberately not checked
 * against the entry's declared field names.
 */
final class CoRequirement
{
    /**
     * @param list<string> $fields
     */
    private function __construct(
        public readonly array $fields,
        public readonly string $rule,
        public readonly ?CoRequirementCheck $check = null,
    ) {
    }

    /**
     * @param array<mixed> $raw
     */
    public static function fromArray(array $raw): self
    {
        $fields = [];
        foreach (\is_array($raw['fields'] ?? null) ? $raw['fields'] : [] as $field) {
            if (\is_string($field)) {
                $fields[] = $field;
            }
        }

        return new self(
            $fields,
            \is_string($raw['rule'] ?? null) ? $raw['rule'] : '',
            // Absent or unknown means "prose only": the rule still ships, it just lands in
            // validate_admin_action's `unchecked` list instead of being evaluated. The catalog
            // validator is what rejects an unknown value — this stays total.
            \is_string($raw['check'] ?? null) ? CoRequirementCheck::tryFrom($raw['check']) : null,
        );
    }
}
