<?php
/**
 * List available templates use case.
 *
 * Phase 6 Application-layer UseCase that drives the §10.2
 * `GET /clb/v1/editor/templates` endpoint defined in
 * `specifications/rest-api-spec.md`. The class enumerates the
 * §6.4 whitelist of canonical built-in template keys (see
 * {@see \CommerceLinkBuilder\Application\Render\Template\TemplateKey}
 * for the eight `KEY_*` constants and the grammar that constrains
 * them) and projects each entry onto the §10.2 response shape:
 *
 *   - `key`      — verbatim §6.4 template key string.
 *   - `label`    — human-readable display label for the editor UI.
 *   - `supports` — `{ single: bool, grid: bool }` flags indicating
 *                  which editor flow can pick the template.
 *
 * The §10.2 response is read-only and stateless: the eight entries
 * are fixed by the §6.4 whitelist, no provider registry is
 * consulted, and no theme override surface is currently exposed
 * (theme overrides resolve at render time inside the template
 * resolver, not at this enumeration boundary). The UseCase is
 * therefore a pure function — it has no constructor parameters,
 * holds no state, and returns the same value on every call.
 *
 * Why a dedicated UseCase exists despite the trivial body:
 *
 *   - Symmetry with the rest of the Phase 6 editor REST surface.
 *     The slice 6c controller resolves a UseCase per endpoint and
 *     calls `execute()` on it; bypassing the Application layer for
 *     this single endpoint would introduce an asymmetry the §1.3
 *     layering rules forbid.
 *
 *   - Test seam. The controller tests stub the UseCase rather than
 *     reaching into the §6.4 constants directly so the controller's
 *     response-shape mapping can be exercised in isolation.
 *
 *   - Future extension. A subsequent slice may layer theme-supplied
 *     templates onto the §6.4 whitelist; routing the §10.2
 *     enumeration through this UseCase today means that extension
 *     can ship without touching the controller wiring.
 *
 * The returned array is positionally keyed (a `list`) and ordered
 * to match the §10.2 example verbatim: the four `single-*` entries
 * first in §6.4 declaration order, then the four `grid-*` entries
 * in §6.4 declaration order. Each item is a plain associative
 * array — no DTO is introduced for this read-only enumeration
 * because the REST mapper layer in slice 6c-controller will pass
 * the array through directly.
 *
 * @package CommerceLinkBuilder\Application\Editor\UseCase
 */

declare(strict_types=1);

namespace CommerceLinkBuilder\Application\Editor\UseCase;

use CommerceLinkBuilder\Application\Render\Template\TemplateKey;

/**
 * Phase 6 UseCase that drives the §10.2
 * `GET /clb/v1/editor/templates` endpoint.
 *
 * See the file-level docblock for the §6.4 whitelist this UseCase
 * projects, the §10.2 response shape it produces, and the
 * rationale for keeping the enumeration on the Application layer
 * despite the trivial body.
 */
final class ListAvailableTemplatesUseCase {

	/**
	 * Execute the §10.2 enumeration.
	 *
	 * Returns the eight §6.4 whitelist entries in §10.2 example
	 * order — single-* keys first, then grid-* keys, each in §6.4
	 * declaration order. Each entry is a plain associative array
	 * matching the §10.2 response shape verbatim:
	 *
	 *   ```
	 *   {
	 *       key:      string,
	 *       label:    string,
	 *       supports: { single: bool, grid: bool }
	 *   }
	 *   ```
	 *
	 * @return list<array{key: string, label: string, supports: array{single: bool, grid: bool}}>
	 */
	public function execute(): array {
		return array(
			array(
				'key'      => TemplateKey::KEY_SINGLE_DEFAULT_CARD,
				'label'    => 'Single / Default Card',
				'supports' => array(
					'single' => true,
					'grid'   => false,
				),
			),
			array(
				'key'      => TemplateKey::KEY_SINGLE_COMPACT_CARD,
				'label'    => 'Single / Compact Card',
				'supports' => array(
					'single' => true,
					'grid'   => false,
				),
			),
			array(
				'key'      => TemplateKey::KEY_SINGLE_MINIMAL_CTA,
				'label'    => 'Single / Minimal CTA',
				'supports' => array(
					'single' => true,
					'grid'   => false,
				),
			),
			array(
				'key'      => TemplateKey::KEY_SINGLE_FALLBACK_CARD,
				'label'    => 'Single / Fallback Card',
				'supports' => array(
					'single' => true,
					'grid'   => false,
				),
			),
			array(
				'key'      => TemplateKey::KEY_GRID_DEFAULT,
				'label'    => 'Grid / Default',
				'supports' => array(
					'single' => false,
					'grid'   => true,
				),
			),
			array(
				'key'      => TemplateKey::KEY_GRID_COMPACT,
				'label'    => 'Grid / Compact',
				'supports' => array(
					'single' => false,
					'grid'   => true,
				),
			),
			array(
				'key'      => TemplateKey::KEY_GRID_RANKING,
				'label'    => 'Grid / Ranking',
				'supports' => array(
					'single' => false,
					'grid'   => true,
				),
			),
			array(
				'key'      => TemplateKey::KEY_GRID_TILE,
				'label'    => 'Grid / Tile',
				'supports' => array(
					'single' => false,
					'grid'   => true,
				),
			),
		);
	}
}
