<?php
/**
 * Result value object for {@see ListAuditEventsUseCase::execute()}.
 *
 * Phase 2 (KI-006) immutable VO that wraps the §12.4
 * `GET /clb/v1/audit/events` response `data` shape documented in
 * `specifications/rest-api-spec.md`. The VO carries the projected
 * row slice (already shaped by
 * {@see ListAuditEventsUseCase::projectRow()}) plus the
 * pagination axes echoed back from the originating
 * {@see \CommerceLinkBuilder\Infrastructure\Persistence\AuditEventListQuery}
 * so REST consumers can render the pagination envelope without
 * re-issuing the query.
 *
 * Mirrors the {@see \CommerceLinkBuilder\Application\Logs\UseCase\ListLogsResult}
 * shape so the audit list path reuses the same envelope
 * conventions the §12.2 logs surface already established. The
 * REST controller in this slice forwards {@see self::toArray()}
 * verbatim into the §3.1 success envelope's `data` slot.
 *
 * @package CommerceLinkBuilder\Application\Audit\UseCase
 */

declare(strict_types=1);

namespace CommerceLinkBuilder\Application\Audit\UseCase;

/**
 * Immutable result of {@see ListAuditEventsUseCase::execute()}.
 *
 * See the file-level docblock for the §12.4 envelope shape and
 * the relationship between the contained items and the
 * {@see ListAuditEventsUseCase} per-row projection pipeline.
 */
final class ListAuditEventsResult {

	/**
	 * Projected row slice in newest-first order.
	 *
	 * Each entry is the §12.4 envelope row produced by
	 * {@see ListAuditEventsUseCase::projectRow()} carrying
	 * `audit_event_type` / `audit_kind` / `actor` / `target` /
	 * `action` / `result` / `safe_summary` /
	 * `changed_fields_summary` / `request_id` /
	 * `correlation_id` / `job_id` / `created_at` slots.
	 *
	 * @var list<array<string, mixed>>
	 */
	private array $items;

	/**
	 * Total matching rows across every page (after filtering,
	 * before pagination).
	 */
	private int $total;

	/**
	 * 1-based page number echoed back from the originating query.
	 */
	private int $page;

	/**
	 * Records per page echoed back from the originating query.
	 */
	private int $perPage;

	/**
	 * Total page count derived from `$total` / `$perPage`.
	 */
	private int $pageCount;

	/**
	 * Construct the result with explicit values for every axis.
	 *
	 * @param list<array<string, mixed>> $items     Projected row slice.
	 * @param int                        $total     Total matching rows (>= 0).
	 * @param int                        $page      1-based page number (>= 1).
	 * @param int                        $perPage   Records per page (>= 1).
	 * @param int                        $pageCount Total page count (>= 0).
	 */
	public function __construct(
		array $items,
		int $total,
		int $page,
		int $perPage,
		int $pageCount
	) {
		$this->items     = array_values( $items );
		$this->total     = $total;
		$this->page      = $page;
		$this->perPage   = $perPage;
		$this->pageCount = $pageCount;
	}

	/**
	 * Projected row slice in newest-first order.
	 *
	 * @return list<array<string, mixed>>
	 */
	public function items(): array {
		return $this->items;
	}

	/**
	 * Total matching rows across every page.
	 */
	public function total(): int {
		return $this->total;
	}

	/**
	 * 1-based page number echoed back from the originating query.
	 */
	public function page(): int {
		return $this->page;
	}

	/**
	 * Records per page echoed back from the originating query.
	 */
	public function perPage(): int {
		return $this->perPage;
	}

	/**
	 * Total page count derived from `$total` / `$perPage`.
	 */
	public function pageCount(): int {
		return $this->pageCount;
	}

	/**
	 * Render the §12.4 success envelope `data` shape:
	 *
	 *   `array(
	 *       'items'      => list<array<string, mixed>>,
	 *       'page'       => int,
	 *       'per_page'   => int,
	 *       'total'      => int,
	 *       'page_count' => int,
	 *   )`
	 *
	 * @return array{
	 *     items: list<array<string, mixed>>,
	 *     page: int,
	 *     per_page: int,
	 *     total: int,
	 *     page_count: int,
	 * }
	 */
	public function toArray(): array {
		return array(
			'items'      => $this->items,
			'page'       => $this->page,
			'per_page'   => $this->perPage,
			'total'      => $this->total,
			'page_count' => $this->pageCount,
		);
	}
}
