<?php

declare(strict_types=1);

namespace Plugin\tnt_mcp\src\Mcp\Action;

/**
 * One table the before-snapshot must cover, declared rather than inferred: a controller that
 * looks like it edits one row routinely rewrites four child tables and, in the shipping case,
 * flips registration flags in `tland` as well. Nothing outside a human reading that controller
 * knows this, so an undone action is only as complete as this list.
 *
 * `columns` narrows a whole-table snapshot to the few columns that actually change, which is what
 * makes snapshotting a 250-row lookup table unconditionally affordable.
 */
final class JournalScope
{
    /**
     * @param array<string,mixed> $by      column => literal or `{{args.…}}` placeholder
     * @param list<string>        $columns empty means every column
     */
    private function __construct(
        public readonly string $table,
        public readonly array $by,
        public readonly array $columns,
        public readonly ?string $note,
    ) {
    }

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

        return new self(
            \is_string($raw['table'] ?? null) ? $raw['table'] : '',
            $by,
            $columns,
            \is_string($raw['note'] ?? null) ? $raw['note'] : null,
        );
    }
}
