<?php
/**
 * Resolves Grundpreis from WooCommerce Germanized.
 *
 * @package PhoenixWP\PriceLabels
 */

declare(strict_types=1);

namespace PhoenixWP\PriceLabels\Compliance\Providers;

use PhoenixWP\PriceLabels\Compliance\Unit_Price_Provider_Interface;
use PhoenixWP\PriceLabels\Compliance\Unit_Price_Text;
use WC_Product;

defined( 'ABSPATH' ) || exit;

/**
 * Uses wc_gzd_get_product() HTML output or Germanized meta fields.
 */
final class Germanized_Provider implements Unit_Price_Provider_Interface {

	public function get_id(): string {
		return 'germanized';
	}

	public function resolve( WC_Product $product ): ?string {
		if ( ! function_exists( 'wc_gzd_get_product' ) ) {
			return null;
		}

		$gzd = wc_gzd_get_product( $product );

		if ( ! is_object( $gzd ) || ! method_exists( $gzd, 'has_unit' ) || ! $gzd->has_unit() ) {
			return null;
		}

		if ( method_exists( $gzd, 'get_unit_price_html' ) ) {
			$html = (string) $gzd->get_unit_price_html();
			$text = Unit_Price_Text::normalize( $html );

			if ( '' !== $text ) {
				return $text;
			}
		}

		return $this->resolve_from_meta( $product, $gzd );
	}

	/**
	 * @param object $gzd Germanized product wrapper.
	 */
	private function resolve_from_meta( WC_Product $product, object $gzd ): ?string {
		$unit_price = method_exists( $gzd, 'get_unit_price' ) ? (float) $gzd->get_unit_price() : 0.0;
		$base       = method_exists( $gzd, 'get_unit_base' ) ? (float) $gzd->get_unit_base() : 0.0;
		$unit       = method_exists( $gzd, 'get_unit_html' ) ? Unit_Price_Text::normalize( (string) $gzd->get_unit_html() ) : '';

		if ( $unit_price <= 0 ) {
			$unit_price = $this->calculate_unit_price( $product, $gzd );
		}

		if ( $unit_price <= 0 || '' === $unit ) {
			return null;
		}

		return Unit_Price_Text::format_per_unit( $unit_price, $base > 0 ? $base : 1.0, $unit );
	}

	/**
	 * @param object $gzd Germanized product wrapper.
	 */
	private function calculate_unit_price( WC_Product $product, object $gzd ): float {
		$product_amount = method_exists( $gzd, 'get_unit_product' ) ? (float) $gzd->get_unit_product() : 0.0;
		$base           = method_exists( $gzd, 'get_unit_base' ) ? (float) $gzd->get_unit_base() : 0.0;

		if ( $product_amount <= 0 ) {
			return 0.0;
		}

		if ( $base <= 0 ) {
			$base = 1.0;
		}

		$display = (float) wc_get_price_to_display( $product );

		return $display > 0 ? ( $display / $product_amount ) * $base : 0.0;
	}
}
