<?php

declare( strict_types=1 );

namespace Simplyin\Simplyin_W_Plugin\Tests\Unit;

use PHPUnit\Framework\TestCase;
use ReflectionMethod;
use Simplyin\Simplyin_W_Plugin\Dto\Order\Order_DTO_Factory;

/**
 * Client-side normalization of the open product-attributes bag:
 * trim, omit blank name/value, multibyte-safe truncation, case-insensitive dedupe
 * (first wins), array flattening and the 30-entry cap. Pure logic — no WooCommerce.
 */
final class Order_Attributes_Test extends TestCase {

	/**
	 * @param array<int, array{name: string, value: mixed}> $pairs
	 * @return array<int, array{name: string, value: string}>
	 */
	private function normalize( array $pairs ): array {
		$method = new ReflectionMethod( Order_DTO_Factory::class, 'normalize_attribute_pairs' );
		$method->setAccessible( true );

		return $method->invoke( null, $pairs );
	}

	public function test_omits_blank_name_or_value(): void {
		$result = $this->normalize(
			[
				[ 'name' => 'color', 'value' => 'red' ],
				[ 'name' => '', 'value' => 'x' ],
				[ 'name' => 'size', 'value' => '' ],
				[ 'name' => '  ', 'value' => '  ' ],
			]
		);

		$this->assertSame( [ [ 'name' => 'color', 'value' => 'red' ] ], $result );
	}

	public function test_trims_name_and_value(): void {
		$result = $this->normalize( [ [ 'name' => '  color  ', 'value' => '  red  ' ] ] );

		$this->assertSame( [ [ 'name' => 'color', 'value' => 'red' ] ], $result );
	}

	public function test_dedupes_case_insensitively_first_wins(): void {
		$result = $this->normalize(
			[
				[ 'name' => 'Color', 'value' => 'red' ],
				[ 'name' => 'color', 'value' => 'blue' ],
			]
		);

		$this->assertSame( [ [ 'name' => 'Color', 'value' => 'red' ] ], $result );
	}

	public function test_flattens_array_value(): void {
		$result = $this->normalize( [ [ 'name' => 'tags', 'value' => [ 'a', 'b', 'c' ] ] ] );

		$this->assertSame( [ [ 'name' => 'tags', 'value' => 'a, b, c' ] ], $result );
	}

	public function test_truncates_long_value_multibyte_safe(): void {
		if ( ! function_exists( 'mb_strlen' ) || ! function_exists( 'mb_substr' ) ) {
			$this->markTestSkipped( 'mbstring extension not available; production code falls back to byte-based substr' );
		}
		$value  = str_repeat( 'ą', 600 ); // 600 multibyte chars.
		$result = $this->normalize( [ [ 'name' => 'description', 'value' => $value ] ] );

		$this->assertCount( 1, $result );
		$this->assertSame( 500, mb_strlen( $result[0]['value'] ) );
		$this->assertSame( str_repeat( 'ą', 500 ), $result[0]['value'] );
	}

	public function test_caps_at_thirty_entries(): void {
		$pairs = [];
		for ( $i = 0; $i < 45; $i++ ) {
			$pairs[] = [ 'name' => "attr_$i", 'value' => "v$i" ];
		}

		$this->assertCount( 30, $this->normalize( $pairs ) );
	}
}
