<?php

declare(strict_types=1);

namespace Australcode\Rewards\Infrastructure\Earning;

use Australcode\Rewards\Domain\Earning\EarningOverrideResolver;

defined( 'ABSPATH' ) || exit;

/**
 * Reads per-product and per-category earning overrides from meta:
 *  - product post meta _acrwd_earn_multiplier / _acrwd_earn_excluded
 *  - product_cat term meta _acrwd_earn_multiplier / _acrwd_earn_excluded
 *
 * Resolution (resolve()): exclusion wins (→ 0.0); else the product's own
 * multiplier; else the highest multiplier among its categories; else 1.0.
 */
final class MetaEarningOverrideResolver implements EarningOverrideResolver {

	public const MULTIPLIER_META = '_acrwd_earn_multiplier';
	public const EXCLUDED_META   = '_acrwd_earn_excluded';

	public function multiplier_for_product( int $product_id ): float {
		if ( $product_id <= 0 ) {
			return 1.0;
		}

		$excluded = '1' === (string) get_post_meta( $product_id, self::EXCLUDED_META, true );

		$product_raw        = get_post_meta( $product_id, self::MULTIPLIER_META, true );
		$product_multiplier = '' !== (string) $product_raw ? (float) $product_raw : null;

		$category_multipliers = array();
		$terms                = get_the_terms( $product_id, 'product_cat' );
		if ( is_array( $terms ) ) {
			foreach ( $terms as $term ) {
				if ( '1' === (string) get_term_meta( $term->term_id, self::EXCLUDED_META, true ) ) {
					$excluded = true;
				}
				$raw = get_term_meta( $term->term_id, self::MULTIPLIER_META, true );
				if ( '' !== (string) $raw ) {
					$category_multipliers[] = (float) $raw;
				}
			}
		}

		return self::resolve( $product_multiplier, $category_multipliers, $excluded );
	}

	/**
	 * Pure resolution: exclusion → 0.0; else product multiplier (if > 0); else the
	 * highest positive category multiplier; else 1.0.
	 *
	 * @param float[] $category_multipliers
	 */
	public static function resolve( ?float $product_multiplier, array $category_multipliers, bool $excluded ): float {
		if ( $excluded ) {
			return 0.0;
		}
		if ( null !== $product_multiplier && $product_multiplier > 0 ) {
			return $product_multiplier;
		}

		$max = 0.0;
		foreach ( $category_multipliers as $multiplier ) {
			if ( $multiplier > $max ) {
				$max = $multiplier;
			}
		}

		return $max > 0 ? $max : 1.0;
	}
}
