<?php
/**
 * Parses localized price strings (es-AR and US formats) into floats.
 *
 * @package EmberPrice
 */

namespace EmberPrice\Ingestion;

/**
 * Handles both `"$ 1.234,56"` (es-AR: `.` thousands, `,` decimal) and
 * `"1,234.56"` (US: `,` thousands, `.` decimal), plus plain single-separator
 * and unseparated values. Pure PHP, no WordPress dependency.
 */
final class PriceParser {

	/**
	 * Parses a localized price string into a float, or null if it doesn't
	 * contain a parseable number.
	 *
	 * @param string|null $raw The raw price string to parse.
	 */
	public function parse( ?string $raw ): ?float {
		if ( null === $raw ) {
			return null;
		}

		// Strip currency symbols, spaces (incl. NBSP), and anything that
		// isn't a digit, separator or minus sign.
		$value = preg_replace( '/[^0-9,.\-]/u', '', $raw );

		if ( null === $value || '' === $value || ! preg_match( '/\d/', $value ) ) {
			return null;
		}

		$negative = str_starts_with( $value, '-' );
		$value    = ltrim( $value, '-' );

		$has_comma = false !== strpos( $value, ',' );
		$has_dot   = false !== strpos( $value, '.' );

		if ( $has_comma && $has_dot ) {
			$value = $this->normalize_mixed_separators( $value );
		} elseif ( $has_comma ) {
			$value = $this->normalize_single_separator( $value, ',' );
		} elseif ( $has_dot ) {
			$value = $this->normalize_single_separator( $value, '.' );
		}

		if ( ! is_numeric( $value ) ) {
			return null;
		}

		$float = (float) $value;

		return $negative ? -$float : $float;
	}

	/**
	 * Both `,` and `.` are present: whichever comes last is the decimal
	 * separator (es-AR `1.234,56` vs. US `1,234.56`).
	 *
	 * @param string $value Digits/separators only, no sign.
	 */
	private function normalize_mixed_separators( string $value ): string {
		$last_comma = strrpos( $value, ',' );
		$last_dot   = strrpos( $value, '.' );

		if ( $last_comma > $last_dot ) {
			// es-AR: '.' thousands, ',' decimal.
			return str_replace( ',', '.', str_replace( '.', '', $value ) );
		}

		// US: ',' thousands, '.' decimal.
		return str_replace( ',', '', $value );
	}

	/**
	 * Only one separator type is present. Repeated occurrences (e.g.
	 * `1.234.567`) are always thousands grouping. A single occurrence
	 * followed by exactly 3 digits is treated as thousands grouping too
	 * (es-AR `1.234` = 1234); any other digit count is treated as decimal.
	 *
	 * @param string $value     Digits/separators only, no sign.
	 * @param string $separator Either `,` or `.`.
	 */
	private function normalize_single_separator( string $value, string $separator ): string {
		if ( substr_count( $value, $separator ) > 1 ) {
			return str_replace( $separator, '', $value );
		}

		$position     = strpos( $value, $separator );
		$digits_after = strlen( $value ) - $position - 1;

		if ( 3 === $digits_after ) {
			return str_replace( $separator, '', $value );
		}

		return str_replace( $separator, '.', $value );
	}
}
