<?php

namespace Acms\Services\Setup\Http;

/**
 * setup の HTTP レスポンスを表す値オブジェクト。
 *
 * 旧コードは各コントローラの中で print / header / die を直接呼んでいたが、Action は本オブジェクトを
 * 返すだけにし、実際の出力（ヘッダ送出・本文 echo）は境界の {@see emit} 1 箇所に集約する。
 */
final class Response
{
    /**
     * @param array<string, string> $headers
     */
    private function __construct(
        private readonly int $status,
        private readonly array $headers,
        private readonly string $body,
    ) {
    }

    public static function html(string $body, int $status = 200): self
    {
        return new self($status, ['Content-Type' => 'text/html; charset=UTF-8'], $body);
    }

    public static function redirect(string $location): self
    {
        return new self(302, ['Location' => $location], '');
    }

    public function status(): int
    {
        return $this->status;
    }

    public function body(): string
    {
        return $this->body;
    }

    /**
     * @return array<string, string>
     */
    public function headers(): array
    {
        return $this->headers;
    }

    /**
     * ステータス・ヘッダを送出し、本文を出力する。境界（エントリ）でのみ呼ぶ。
     */
    public function emit(): void
    {
        if (!headers_sent()) {
            http_response_code($this->status);
            foreach ($this->headers as $name => $value) {
                header($name . ': ' . $value);
            }
        }
        if ($this->body !== '') {
            print $this->body;
        }
    }
}
