<?php

namespace CelerSearch\Builders;

/**
 * Fluent builder for the `get_available_searchable_attributes()` whitelist.
 *
 * Centralizes the shape that index implementations emit and the Vue picker
 * consumes. Supports optional group labels so the picker can render native
 * <optgroup> sections for readability.
 *
 * Example:
 *
 *     $builder = new SearchableAttributesBuilder();
 *     $builder->group( __( 'Content', 'celersearch' ) )
 *         ->entry( 'post_title', __( 'Product title', 'celersearch' ) )
 *         ->entry( 'sku', __( 'SKU', 'celersearch' ) );
 *     $builder->group( __( 'Taxonomies', 'celersearch' ) )
 *         ->entries( $this->collect_searchable_taxonomies() );
 *     return $builder->build();
 */
class SearchableAttributesBuilder {

	/**
	 * @var array<int, array{name:string, label:string, group:?string}>
	 */
	protected array $entries = [];

	/**
	 * Currently active group for subsequent entries. Null means ungrouped.
	 *
	 * @var string|null
	 */
	protected ?string $current_group = null;

	/**
	 * Set the active group label for subsequent entry() calls. Pass null or
	 * '' to reset to an ungrouped context.
	 *
	 * @param string|null $label
	 *
	 * @return self
	 */
	public function group( ?string $label ): self {
		$this->current_group = ( null === $label || '' === $label ) ? null : $label;
		return $this;
	}

	/**
	 * Append a single entry. When $group is omitted the active group from
	 * the last group() call is used.
	 *
	 * @param string      $name
	 * @param string      $label
	 * @param string|null $group
	 *
	 * @return self
	 */
	public function entry( string $name, string $label, ?string $group = null ): self {
		$this->entries[] = [
			'name'  => $name,
			'label' => $label,
			'group' => $group ?? $this->current_group,
		];
		return $this;
	}

	/**
	 * Append many entries from a pre-built list (e.g. the return value of
	 * a collect_* helper). Each $entries item must have 'name'; 'label' and
	 * 'group' are optional.
	 *
	 * @param array       $entries
	 * @param string|null $group   Overrides the per-entry group and the active group.
	 *
	 * @return self
	 */
	public function entries( array $entries, ?string $group = null ): self {
		$override = $group ?? $this->current_group;
		foreach ( $entries as $e ) {
			if ( ! is_array( $e ) || empty( $e['name'] ) ) {
				continue;
			}
			$this->entries[] = [
				'name'  => (string) $e['name'],
				'label' => isset( $e['label'] ) ? (string) $e['label'] : (string) $e['name'],
				'group' => $e['group'] ?? $override,
			];
		}
		return $this;
	}

	/**
	 * Finalize and return the array of entries in declaration order.
	 *
	 * @return array<int, array{name:string, label:string, group:?string}>
	 */
	public function build(): array {
		return $this->entries;
	}
}
