<?php
/**
 * Fallback product search-keywords extractor.
 *
 * @package Affilun\Application\Product
 */

declare(strict_types=1);

namespace Affilun\Application\Product;

use Affilun\Domain\Product\ProductSnapshot;

/**
 * Builds deterministic keywords from the saved brand/title only.
 */
final class FallbackProductSearchKeywordsExtractor implements ProductSearchKeywordsExtractor {

	/**
	 * Extract normalized search keywords.
	 *
	 * @param ProductSnapshot $snapshot Product snapshot being saved.
	 */
	public function extract( ProductSnapshot $snapshot ): SearchKeywordsExtractionResult {
		$parts = array();
		if ( $snapshot->brand() !== null ) {
			$parts[] = $snapshot->brand();
		}
		$parts[] = $snapshot->title();

		return new SearchKeywordsExtractionResult(
			$this->truncate( implode( ' ', $parts ), 512 ),
			'fallback_title'
		);
	}

	/**
	 * Bound keywords to the DB column size.
	 *
	 * @param string $value Raw keywords.
	 * @param int    $max   Maximum length.
	 */
	private function truncate( string $value, int $max ): string {
		$normalized = trim( preg_replace( '/\s+/u', ' ', $value ) ?? $value );
		if ( function_exists( 'mb_substr' ) ) {
			return mb_substr( $normalized, 0, $max, 'UTF-8' );
		}

		return substr( $normalized, 0, $max );
	}
}
