<?php
/**
 * Stripe-compatible currency codes for admin selectors.
 *
 * @package WPDudeProducts
 */

declare(strict_types=1);

namespace WPDude\Products\Support;

/**
 * Currency dropdown options (priority codes first).
 */
final class Currencies {

	/**
	 * Shown first in selectors (most common for merchants).
	 *
	 * @var list<string>
	 */
	public const PRIORITY = array( 'gbp', 'usd', 'eur', 'cad', 'aud' );

	/**
	 * Human-readable names for priority currencies.
	 *
	 * @var array<string, string>
	 */
	private const PRIORITY_NAMES = array(
		'gbp' => 'British pound',
		'usd' => 'US dollar',
		'eur' => 'Euro',
		'cad' => 'Canadian dollar',
		'aud' => 'Australian dollar',
	);

	/**
	 * Lowercase ISO codes supported for Stripe Checkout presentment.
	 *
	 * @var list<string>
	 */
	private const CODES = array(
		'aed', 'aud', 'bgn', 'brl', 'cad', 'chf', 'clp', 'cny', 'cop', 'czk',
		'dkk', 'egp', 'eur', 'gbp', 'hkd', 'huf', 'idr', 'ils', 'inr', 'jpy',
		'krw', 'mxn', 'myr', 'nok', 'nzd', 'php', 'pkr', 'pln', 'ron', 'rub',
		'sar', 'sek', 'sgd', 'thb', 'try', 'twd', 'uah', 'usd', 'vnd', 'zar',
	);

	/**
	 * Whether a code is allowed.
	 */
	public static function is_allowed( string $code ): bool {
		$code = strtolower( trim( $code ) );
		return '' !== $code && in_array( $code, self::CODES, true );
	}

	/**
	 * Normalize to a supported lowercase code, or fallback.
	 */
	public static function sanitize( string $code, string $fallback = 'gbp' ): string {
		$code = strtolower( sanitize_text_field( $code ) );
		if ( self::is_allowed( $code ) ) {
			return $code;
		}
		$fallback = strtolower( $fallback );
		return self::is_allowed( $fallback ) ? $fallback : 'gbp';
	}

	/**
	 * Option label for a currency code.
	 */
	public static function label( string $code ): string {
		$code = strtolower( $code );
		$iso  = strtoupper( $code );
		if ( isset( self::PRIORITY_NAMES[ $code ] ) ) {
			return sprintf( '%s — %s', $iso, self::PRIORITY_NAMES[ $code ] );
		}
		return $iso;
	}

	/**
	 * Output a currency &lt;select&gt; with popular codes grouped at the top.
	 *
	 * @param array<string, string> $attrs Extra attributes.
	 */
	public static function render_select( string $name, string $id, string $selected, array $attrs = array() ): void {
		$selected = strtolower( $selected );
		$priority = self::PRIORITY;
		$rest     = array_values( array_diff( self::CODES, $priority ) );
		sort( $rest );

		echo '<select name="' . esc_attr( $name ) . '" id="' . esc_attr( $id ) . '"';
		foreach ( $attrs as $key => $value ) {
			echo ' ' . esc_attr( (string) $key ) . '="' . esc_attr( (string) $value ) . '"';
		}
		echo '>';

		echo '<optgroup label="' . esc_attr__( 'Popular', 'dude-commerce' ) . '">';
		foreach ( $priority as $code ) {
			printf(
				'<option value="%1$s" %2$s>%3$s</option>',
				esc_attr( $code ),
				selected( $selected, $code, false ),
				esc_html( self::label( $code ) )
			);
		}
		echo '</optgroup>';

		echo '<optgroup label="' . esc_attr__( 'All currencies', 'dude-commerce' ) . '">';
		foreach ( $rest as $code ) {
			printf(
				'<option value="%1$s" %2$s>%3$s</option>',
				esc_attr( $code ),
				selected( $selected, $code, false ),
				esc_html( self::label( $code ) )
			);
		}
		echo '</optgroup>';

		echo '</select>';
	}
}
