<?php
/**
 * Cart handling for VAT.
 *
 * @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.0
 */

namespace EDD\Pro\Taxes\VAT;

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

use EDD\EventManagement\SubscriberInterface;

/**
 * Stores the current state of VAT in the EDD cart.
 */
class Cart implements SubscriberInterface {

	const SESSION_KEY = 'vat';

	/**
	 * The current VAT information.
	 *
	 * @var Result
	 */
	private $vat_details;

	/**
	 * Whether the VAT is reverse charged in the cart.
	 *
	 * @var bool
	 */
	private $is_reverse_charged = false;

	/**
	 * Returns the list of events to subscribe to.
	 *
	 * @since 3.5.0
	 * @return array
	 */
	public static function get_subscribed_events() {
		return array(
			'edd_cart_contents_loaded_from_session' => 'restore',
			'wp'                                    => 'check_billing_country',
			'edd_empty_cart'                        => 'clear',
			'shutdown'                              => array( 'save', 1 ),
		);
	}

	/**
	 * Checks a VAT number.
	 *
	 * @since 3.5.0
	 * @param string $vat_number   The VAT number to check.
	 * @param string $country_code The country code of the VAT number.
	 */
	public function check_vat_number( $vat_number, $country_code ) {
		$this->vat_details        = Validator::check_vat( $vat_number, $country_code );
		$this->is_reverse_charged = false;

		if ( $this->vat_details->is_valid() ) {
			$this->is_reverse_charged = Utility::can_reverse_charge_vat( $country_code );
		}
	}

	/**
	 * Returns the VAT details result.
	 *
	 * @since 3.5.0
	 * @return Result
	 */
	public function get_vat_details() {
		return $this->vat_details;
	}

	/**
	 * Check whether the VAT has been reverse charged.
	 *
	 * @since 3.5.0
	 * @return bool
	 */
	public function is_reverse_charged(): bool {
		return (bool) $this->is_reverse_charged;
	}

	/**
	 * Applies the VAT details if a cart is restored.
	 *
	 * @param \EDD_Cart $cart The cart object.
	 * @since 3.5.0
	 */
	public function restore( $cart ) {

		$vat_session = \EDD()->session->get( self::SESSION_KEY );
		if ( ! $vat_session || ! isset( $vat_session['is_reverse_charged'], $vat_session['vat_check'] ) ) {
			return;
		}

		$this->is_reverse_charged = (bool) $vat_session['is_reverse_charged'];
		$this->vat_details        = null;

		edd_debug_log( 'EUVAT: cart restored with: ' . print_r( $vat_session, true ) );

		if ( ! empty( $vat_session['vat_check'] ) && is_array( $vat_session['vat_check'] ) ) {
			$vat_check_array = array_merge(
				array_fill_keys( array( 'vat_number', 'country_code', 'valid', 'name', 'address', 'error', 'consultation_number' ), '' ),
				$vat_session['vat_check']
			);

			if ( ! empty( $vat_check_array['vat_number'] ) ) {
				$vat_check                      = new Result( $vat_check_array['vat_number'], $vat_check_array['country_code'] );
				$vat_check->valid               = $vat_check_array['valid'];
				$vat_check->name                = $vat_check_array['name'];
				$vat_check->address             = $vat_check_array['address'];
				$vat_check->error               = $vat_check_array['error'];
				$vat_check->consultation_number = $vat_check_array['consultation_number'];

				$this->vat_details = $vat_check;
			}
		}
	}

	/**
	 * Check if the billing country matches the saved VAT details and clear if not.
	 *
	 * @since 3.5.0
	 */
	public function check_billing_country() {
		if ( ! edd_is_checkout() ) {
			return;
		}

		if ( empty( $this->vat_details ) ) {
			return;
		}

		$customer = \EDD\Sessions\Customer::get();
		if ( $customer && ! empty( $customer['address']['country'] ) && '*' !== $customer['address']['country'] ) {
			$selected_country = $customer['address']['country'];
		} else {
			$selected_country = edd_get_shop_country();
		}

		// If selected country on checkout doesn't match saved VAT country, we clear the state.
		if ( $selected_country !== $this->vat_details->country_code ) {
			edd_debug_log( 'EUVAT: cleared VAT selected country on checkout doesn\'t match saved VAT country (' . $selected_country . ') - (' . $this->vat_details->country_code . ')' );
			$this->clear();
		}
	}

	/**
	 * Saves the VAT check to the cart session.
	 *
	 * @since 3.5.0
	 */
	public function save() {
		$vat_details = $this->get_vat_details();
		if ( empty( $vat_details ) ) {
			return;
		}

		\EDD()->session->set(
			self::SESSION_KEY,
			array(
				'is_reverse_charged' => $this->is_reverse_charged(),
				'vat_check'          => (array) $vat_details,
			)
		);
	}

	/**
	 * Clear the VAT check from the cart session.
	 *
	 * @since 3.5.0
	 */
	public function clear() {
		\EDD()->session->set( self::SESSION_KEY, null );
		$this->is_reverse_charged = false;
		$this->vat_details        = null;
	}
}
