<?php

namespace Acms\Services\Setup\Tool;

/**
 * ツールの処理結果を Responder に渡す不変ペイロード（ADR の Domain Payload 相当）。
 *
 * 旧 Surfacer は `$this->Post` / `$this->Error` を書き換えて画面状態を伝えていたが、本オブジェクトを
 * 返すことで「どの画面を・どんなエラー/通知・どんな View データで描くか」を明示的な戻り値にする。
 * 生成は名前付きコンストラクタ（{@see form} / {@see invalid} / {@see done}）に集約し、多段ツールは
 * {@see on} で任意の screen トークンを指定する。
 */
final class ToolView
{
    /**
     * @param array<string, mixed> $notices
     * @param array<string, mixed> $data 画面固有の View データ（一覧・再表示入力値など）
     */
    private function __construct(
        public readonly string $screen,
        public readonly ToolErrors $errors,
        public readonly array $notices,
        public readonly array $data,
    ) {
    }

    /**
     * 入力フォーム（初期表示）。
     *
     * @param array<string, mixed> $data
     */
    public static function form(array $data = []): self
    {
        return new self(Screen::Form->value, new ToolErrors(), [], $data);
    }

    /**
     * バリデーション/実行エラーでフォーム再表示。
     *
     * @param array<string, mixed> $data
     */
    public static function invalid(ToolErrors $errors, array $data = []): self
    {
        return new self(Screen::Invalid->value, $errors, [], $data);
    }

    /**
     * 実行完了。
     *
     * @param array<string, mixed> $data
     * @param array<string, mixed> $notices
     */
    public static function done(array $data = [], array $notices = []): self
    {
        return new self(Screen::Done->value, new ToolErrors(), $notices, $data);
    }

    /**
     * 多段ツール（SystemUpdate の 'drop' / 'complete' 等）向けに任意の screen トークンで組む。
     *
     * @param array<string, mixed> $data
     * @param array<string, mixed> $notices
     */
    public static function on(string $screen, array $data = [], ?ToolErrors $errors = null, array $notices = []): self
    {
        return new self($screen, $errors ?? new ToolErrors(), $notices, $data);
    }
}
