<?php
/**
 * Recurring handling for taxes.
 *
 * @package     EDD\Pro\Taxes\VAT
 * @copyright   Copyright (c) 2025, Sandhills Development, LLC
 * @license     https://opensource.org/licenses/gpl-2.0.php GNU Public License
 * @since       3.5.1
 */

namespace EDD\Pro\Taxes\VAT;

use EDD\EventManagement\SubscriberInterface;
use EDD\Orders\Order;
use EDD_Subscription;

/**
 * Adds VAT handling to recurring payments.
 *
 * @since 3.5.1
 */
class Recurring implements SubscriberInterface {

	/**
	 * The current VAT state of the cart.
	 *
	 * @var Cart
	 */
	private $cart;

	/**
	 * Constructor.
	 */
	public function __construct( Cart $cart ) {
		$this->cart = $cart;
	}

	/**
	 * Gets the subscribed events.
	 *
	 * @since 3.5.1
	 * @return array
	 */
	public static function get_subscribed_events(): array {
		return array(
			'edd_recurring_add_subscription_order'         => array( 'update_renewal_order', 5, 2 ),
			'edd_recurring_purchase_data'                  => 'update_purchase_data',
			'edd_recurring_subscription_recurring_amounts' => array( 'update_subscription_amounts', 100, 5 ),
		);
	}

	/**
	 * Add VAT details to a renewal order.
	 *
	 * @since 3.5.1
	 * @param Order            $order        The order object.
	 * @param EDD_Subscription $subscription The subscription object.
	 */
	public function update_renewal_order( Order $order, EDD_Subscription $subscription ) {
		$parent_payment_id = $subscription->parent_payment_id;
		if ( empty( $parent_payment_id ) ) {
			return;
		}

		if ( edd_get_order_meta( $parent_payment_id, '_edd_payment_vat_reverse_charged', true ) ) {
			edd_update_order_meta( $order->id, '_edd_payment_vat_reverse_charged', true );
		}

		if ( edd_get_order_meta( $parent_payment_id, '_edd_payment_vat_is_eu', true ) ) {
			edd_update_order_meta( $order->id, '_edd_payment_vat_is_eu', true );
		}

		$vat_number = edd_get_order_meta( $parent_payment_id, '_edd_payment_vat_number', true );
		if ( ! $vat_number ) {
			return;
		}

		edd_update_order_meta( $order->id, '_edd_payment_vat_number', $vat_number );
		edd_update_order_meta( $order->id, '_edd_payment_vat_number_valid', edd_get_order_meta( $parent_payment_id, '_edd_payment_vat_number_valid', true ) );
		edd_update_order_meta( $order->id, '_edd_payment_vat_company_name', edd_get_order_meta( $parent_payment_id, '_edd_payment_vat_company_name', true ) );
		edd_update_order_meta( $order->id, '_edd_payment_vat_company_address', edd_get_order_meta( $parent_payment_id, '_edd_payment_vat_company_address', true ) );
	}

	/**
	 * When VAT is applied to the parent order, mark it on cart items so VAT can be removed from recurring subscriptions.
	 *
	 * @since 3.5.1
	 * @param array $purchase_data The purchase data.
	 * @return array The purchase data.
	 */
	public function update_purchase_data( $purchase_data ) {

		if ( empty( $purchase_data['purchase_key'] ) ) {
			return $purchase_data;
		}

		$order = edd_get_order_by( 'payment_key', $purchase_data['purchase_key'] );
		if ( empty( $order ) || is_wp_error( $order ) ) {
			return $purchase_data;
		}

		$is_reverse_charged = filter_var( edd_get_order_meta( $order->id, '_edd_payment_vat_reverse_charged', true ), FILTER_VALIDATE_BOOL );
		if ( ! $is_reverse_charged ) {
			return $purchase_data;
		}

		foreach ( $purchase_data['cart_details'] as $cart_index => $cart_item ) {
			$purchase_data['cart_details'][ $cart_index ]['_vat_reverse_charged'] = $is_reverse_charged;
		}

		return $purchase_data;
	}

	/**
	 * Update subscription amounts to remove VAT if applicable.
	 *
	 * @since 3.5.1
	 * @param array $recurring_amounts The values of the recurring payment being returned.
	 * @param array $item              The cart item being setup as a recurring payment.
	 * @param int   $key               The cart item key.
	 * @param array $cart_details      The cart details.
	 * @param array $cart_discounts    The cart discounts.
	 * @return array The updated recurring amounts.
	 */
	public function update_subscription_amounts( $recurring_amounts, $item, $key, $cart_details, $cart_discounts ) {
		if ( $this->is_item_reverse_charged( $item ) ) {
			if ( ! edd_prices_include_tax() ) {
				$recurring_amounts['amount'] -= ( $recurring_amounts['tax'] ?? 0 );
			}
			$recurring_amounts['tax'] = 0;
		}

		return $recurring_amounts;
	}

	/**
	 * Checks if the item is reverse charged.
	 *
	 * @param array $item The cart item.
	 * @return bool True if the item is reverse charged, false otherwise.
	 */
	private function is_item_reverse_charged( $item ): bool {
		if ( $this->cart->is_reverse_charged() ) {
			return true;
		}

		if ( ! empty( $item['_vat_reverse_charged'] ) ) {
			return true;
		}

		$license = $this->get_license_for_upgrade( $item );
		if ( ! $license || ! $license->payment_id ) {
			return false;
		}

		return ! empty( edd_get_order_meta( $license->payment_id, '_edd_payment_vat_reverse_charged', true ) );
	}

	/**
	 * Gets the license for an upgrade.
	 *
	 * @param array $item The cart item.
	 * @return \EDD_SL_License|false The license object or false if not found.
	 */
	private function get_license_for_upgrade( $item ) {
		if ( ! function_exists( 'edd_software_licensing' ) ) {
			return false;
		}

		if ( empty( $item['item_number']['options']['is_upgrade'] ) ) {
			return false;
		}

		if ( empty( $item['item_number']['options']['license_id'] ) ) {
			return false;
		}

		return edd_software_licensing()->get_license( $item['item_number']['options']['license_id'] );
	}
}
