<?php
/**
 * Admin price formatting helpers.
 *
 * @package Affilun\Presentation\Admin
 */

declare(strict_types=1);

namespace Affilun\Presentation\Admin;

use Affilun\Infrastructure\Persistence\ProductRecord;

/**
 * Formats product prices consistently across wp-admin surfaces.
 */
final class AdminPriceFormatter {

	/**
	 * Format a product record price for admin tables.
	 *
	 * @param ProductRecord $record Product record.
	 */
	public static function formatProductRecord( ProductRecord $record ): string {
		return self::format(
			$record->priceAmount(),
			$record->priceCurrency(),
			$record->priceLabel()
		);
	}

	/**
	 * Format a price from normalized columns or a provider label.
	 *
	 * @param string|null $amount   Numeric amount.
	 * @param string|null $currency ISO currency code.
	 * @param string|null $label    Provider display label.
	 */
	public static function format( ?string $amount, ?string $currency, ?string $label = null ): string {
		$currency = strtoupper( trim( (string) $currency ) );
		$amount   = self::normalizeAmount( $amount );
		if ( $amount !== null ) {
			return self::formatAmount( $amount, $currency === '' ? 'JPY' : $currency );
		}

		$label = trim( (string) $label );
		if ( $label === '' ) {
			return '-';
		}

		$parsedAmount = self::amountFromLabel( $label );
		if ( $parsedAmount !== null ) {
			$labelCurrency = self::currencyFromLabel( $label ) ?? ( $currency === '' ? 'JPY' : $currency );
			return self::formatAmount( $parsedAmount, $labelCurrency );
		}

		return $label;
	}

	/**
	 * Format a normalized numeric amount for one currency.
	 *
	 * @param string $amount   Numeric amount.
	 * @param string $currency ISO currency code.
	 */
	private static function formatAmount( string $amount, string $currency ): string {
		if ( $currency === 'JPY' ) {
			return '￥' . number_format( (int) round( (float) $amount ) );
		}

		return trim( $currency . ' ' . number_format( (float) $amount, 2 ) );
	}

	/**
	 * Normalize numeric strings while preserving decimal intent.
	 *
	 * @param string|null $amount Numeric amount.
	 */
	private static function normalizeAmount( ?string $amount ): ?string {
		if ( $amount === null ) {
			return null;
		}
		$amount = str_replace( ',', '', trim( $amount ) );
		if ( $amount === '' || ! is_numeric( $amount ) ) {
			return null;
		}

		return $amount;
	}

	/**
	 * Extract a numeric amount from a display label.
	 *
	 * @param string $label Provider display label.
	 */
	private static function amountFromLabel( string $label ): ?string {
		if ( preg_match( '/(\d[\d,]*(?:\.\d+)?)/', $label, $matches ) !== 1 ) {
			return null;
		}

		return self::normalizeAmount( $matches[1] );
	}

	/**
	 * Infer currency from a provider label.
	 *
	 * @param string $label Provider display label.
	 */
	private static function currencyFromLabel( string $label ): ?string {
		if ( preg_match( '/\b([A-Z]{3})\b/', $label, $matches ) === 1 ) {
			return strtoupper( $matches[1] );
		}
		if ( str_contains( $label, '¥' ) || str_contains( $label, '￥' ) || str_contains( $label, '円' ) ) {
			return 'JPY';
		}

		return null;
	}
}
