<?php
/**
 * LegalMonetaryTotal class to get the legal monetary total data.
 *
 * @since 1.4.0
 * @package EDD\Invoices\XML\Elements
 */

namespace EDD\Pro\Invoices\XML\Elements;

// Exit if accessed directly.
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore

/**
 * LegalMonetaryTotal class.
 */
class LegalMonetaryTotal extends Element {

	/**
	 * Get the data.
	 *
	 * Uses the order's stored values directly to ensure all monetary amounts
	 * are consistent and match what the customer actually paid.
	 *
	 * @since 1.4.0
	 * @return array
	 */
	protected function get_data(): array {
		$line_extension = (float) $this->order->subtotal;
		$discount       = (float) $this->order->discount;
		$charge_total   = $this->get_fee_subtotal();
		$tax_exclusive  = $line_extension - $discount + $charge_total;

		// UBL 2.1 requires strict element ordering inside cac:LegalMonetaryTotal.
		$children = array(
			array(
				'name'       => 'cbc:LineExtensionAmount',
				'value'      => $this->format_number( $line_extension ),
				'attributes' => array(
					'currencyID' => $this->order->currency,
				),
			),
			array(
				'name'       => 'cbc:TaxExclusiveAmount',
				'value'      => $this->format_number( $tax_exclusive ),
				'attributes' => array(
					'currencyID' => $this->order->currency,
				),
			),
			array(
				'name'       => 'cbc:TaxInclusiveAmount',
				'value'      => $this->format_number( $this->order->total ),
				'attributes' => array(
					'currencyID' => $this->order->currency,
				),
			),
		);

		// BT-107: Only include AllowanceTotalAmount when there is a discount.
		if ( $discount > 0 ) {
			$children[] = array(
				'name'       => 'cbc:AllowanceTotalAmount',
				'value'      => $this->format_number( $discount ),
				'attributes' => array(
					'currencyID' => $this->order->currency,
				),
			);
		}

		// BT-108: Only include ChargeTotalAmount when there are fees.
		if ( $charge_total > 0 ) {
			$children[] = array(
				'name'       => 'cbc:ChargeTotalAmount',
				'value'      => $this->format_number( $charge_total ),
				'attributes' => array(
					'currencyID' => $this->order->currency,
				),
			);
		}

		$children[] = array(
			'name'       => 'cbc:PayableAmount',
			'value'      => $this->format_number( $this->order->total ),
			'attributes' => array(
				'currencyID' => $this->order->currency,
			),
		);

		return array(
			'name'     => 'cac:LegalMonetaryTotal',
			'children' => $children,
		);
	}

	/**
	 * Get the sum of all fee subtotals on the order.
	 *
	 * @since 3.6.7
	 * @return float
	 */
	private function get_fee_subtotal(): float {
		$total = 0.0;
		foreach ( $this->order->get_fees() as $fee ) {
			$total += (float) $fee->subtotal;
		}

		return $total;
	}
}
