<?php
/**
 * Builds label field data from WooCommerce products.
 *
 * @package PhoenixWP\PriceLabels
 */

declare(strict_types=1);

namespace PhoenixWP\PriceLabels\Labels;

use PhoenixWP\PriceLabels\Compliance\Unit_Price_Formatter;
use PhoenixWP\PriceLabels\Labels\Product_Brand_Resolver;
use PhoenixWP\PriceLabels\Labels\Stock_Text_Formatter;
use WC_Product;

defined( 'ABSPATH' ) || exit;

/**
 * Maps WC_Product instances to printable label arrays.
 */
final class Label_Data_Builder {

	/**
	 * Builds label data for one product or variation.
	 *
	 * @param WC_Product $product Product or variation.
	 */
	public function build( WC_Product $product ): array {
		$parent = $product->is_type( 'variation' ) ? wc_get_product( $product->get_parent_id() ) : null;
		$display_name = $parent instanceof WC_Product ? $parent->get_name() : $product->get_name();

		$regular = (float) $product->get_regular_price();
		$sale    = (float) $product->get_sale_price();
		$on_sale = $product->is_on_sale() && $sale > 0;

		$data = array(
			'product_id'     => $product->get_id(),
			'brand'          => Product_Brand_Resolver::resolve( $product ),
			'name'           => $display_name,
			'variation_text' => $this->get_variation_text( $product ),
			'price'          => $this->format_price( (float) wc_get_price_to_display( $product ) ),
			'regular_price'  => $on_sale ? $this->format_price( (float) wc_get_price_to_display( $product, array( 'price' => $regular ) ) ) : '',
			'sale_price'     => $on_sale ? $this->format_price( (float) wc_get_price_to_display( $product, array( 'price' => $sale ) ) ) : '',
			'on_sale'        => $on_sale,
			'unit_price'     => Unit_Price_Formatter::format( $product ),
			'stock'          => Stock_Text_Formatter::format( $product ),
			'sku'            => (string) $product->get_sku(),
			'ean'            => $this->get_ean( $product ),
			'barcode_html'   => '',
		);

		$data = Label_Text_Sanitizer::sanitize_label_data( $data, $product );

		/**
		 * Filters printable label data before PDF rendering.
		 *
		 * @param array<string, mixed> $data    Label fields.
		 * @param WC_Product           $product Source product.
		 */
		return (array) apply_filters( 'phoenix_wp_price_labels_label_data', $data, $product );
	}

	/**
	 * Formats a numeric price for plain-text/PDF output.
	 *
	 * @param float $amount Price amount.
	 */
	private function format_price( float $amount ): string {
		return html_entity_decode( wp_strip_all_tags( wc_price( $amount ) ), ENT_QUOTES, 'UTF-8' );
	}

	/**
	 * Human-readable variation attributes.
	 *
	 * @param WC_Product $product Product.
	 */
	private function get_variation_text( WC_Product $product ): string {
		if ( ! $product->is_type( 'variation' ) ) {
			return '';
		}

		$parts = array();

		foreach ( $product->get_attributes() as $value ) {
			if ( is_string( $value ) && '' !== $value ) {
				$parts[] = $value;
			}
		}

		return implode( ', ', $parts );
	}

	/**
	 * Resolves EAN/GTIN from common WooCommerce meta keys.
	 *
	 * @param WC_Product $product Product.
	 */
	private function get_ean( WC_Product $product ): string {
		$keys = array( '_global_unique_id', '_ean', '_gtin', 'hwp_product_gtin' );

		/**
		 * Filters meta keys checked for EAN/GTIN on price labels.
		 *
		 * @param string[]   $keys    Meta keys in priority order.
		 * @param WC_Product $product Product.
		 */
		$keys = (array) apply_filters( 'phoenix_wp_price_labels_ean_meta_keys', $keys, $product );

		foreach ( $keys as $key ) {
			$value = trim( (string) $product->get_meta( $key ) );
			if ( '' !== $value ) {
				return preg_replace( '/\D/', '', $value ) ?? $value;
			}
		}

		return '';
	}
}
