<?php
/**
 * Amazon discount brand normalization.
 *
 * @package Affilun\Application\AmazonDiscount
 */

declare(strict_types=1);

namespace Affilun\Application\AmazonDiscount;

/**
 * Normalizes priority brands shared by settings, sync and shortcode rendering.
 */
final class AmazonDiscountBrand {

	public const MAX_COUNT  = 10;
	public const MAX_LENGTH = 60;

	private const STORAGE_PREFIX = 'brand:';

	/**
	 * Parse a comma, Japanese-comma or newline separated brand value.
	 *
	 * @param mixed $value Raw shortcode or form value.
	 *
	 * @return list<string>
	 */
	public static function parse( mixed $value ): array {
		if ( is_string( $value ) ) {
			$parts = preg_split( '/[,、\r\n]+/u', $value );
			return self::normalize( is_array( $parts ) ? $parts : array() );
		}
		return is_array( $value ) ? self::normalize( array_values( $value ) ) : array();
	}

	/**
	 * Normalize, deduplicate and bound brand names.
	 *
	 * @param list<mixed> $values Raw values.
	 *
	 * @return list<string>
	 */
	public static function normalize( array $values ): array {
		$brands = array();
		$seen   = array();
		foreach ( $values as $value ) {
			if ( ! is_string( $value ) ) {
				continue;
			}
			$brand = preg_replace( '/[\x00-\x1F\x7F]/u', '', trim( $value ) );
			if ( ! is_string( $brand ) || $brand === '' ) {
				continue;
			}
			$brand = self::truncate( $brand );
			$key   = function_exists( 'mb_strtolower' )
				? mb_strtolower( $brand, 'UTF-8' )
				: strtolower( $brand );
			if ( isset( $seen[ $key ] ) ) {
				continue;
			}
			$seen[ $key ] = true;
			$brands[]     = $brand;
			if ( count( $brands ) >= self::MAX_COUNT ) {
				break;
			}
		}
		return $brands;
	}

	/**
	 * Return the repository key used to isolate one brand snapshot.
	 *
	 * @param string $brand Normalized brand.
	 */
	public static function storageKey( string $brand ): string {
		$normalized = self::normalize( array( $brand ) );
		return self::STORAGE_PREFIX . ( $normalized[0] ?? '' );
	}

	/**
	 * Resolve a brand name from a repository key.
	 *
	 * @param string $key Stored collection key.
	 */
	public static function fromStorageKey( string $key ): ?string {
		if ( ! str_starts_with( $key, self::STORAGE_PREFIX ) ) {
			return null;
		}
		$brand = substr( $key, strlen( self::STORAGE_PREFIX ) );
		return $brand === '' ? null : $brand;
	}

	/**
	 * Truncate a brand without splitting a multibyte character.
	 *
	 * @param string $brand Brand name.
	 */
	private static function truncate( string $brand ): string {
		if ( function_exists( 'mb_substr' ) ) {
			return mb_substr( $brand, 0, self::MAX_LENGTH, 'UTF-8' );
		}
		return substr( $brand, 0, self::MAX_LENGTH );
	}
}
