<?php
/**
 * The admin-specific functionality of the plugin.
 *
 * @package    Authorize_Net_Payments_For_Woocommerce
 * @subpackage Authorize_Net_Payments_For_Woocommerce/admin
 */

if (! defined('ABSPATH')) {
	exit;
}

require_once plugin_dir_path(__FILE__) . '../trait-anet-order-meta.php';

/**
 * The admin-specific functionality of the plugin.
 *
 * Defines the plugin name, version, and two examples hooks for how to
 * enqueue the admin-specific stylesheet and JavaScript.
 *
 * @package    Authorize_Net_Payments_For_Woocommerce
 * @subpackage Authorize_Net_Payments_For_Woocommerce/admin
 */
class Anet_Credit_Card_Admin
{
	use Anet_Order_Meta;
	/**
	 * The ID of this plugin.
	 *
	 * @var      string    $id   The ID of this plugin.
	 */
	private $id;
	/**
	 * The gateway object of this plugin.
	 *
	 * @var      object    $gateway    The current payment gateways object.
	 */
	private $gateway;
	/**
	 * Initialize the class and set its properties.
	 *
	 * @param      string $version    The version of this plugin.
	 * @param      object $gateway The current payment gateways object.
	 */
	public function __construct($version, $gateway)
	{
		$this->id      = ANET_CREDIT_CARD_GATEWAY_ID;
		$this->gateway = $gateway;
		add_action('admin_notices', array($this, 'sandbox_admin_notice'));
	}
	
	/**
	 * Display admin notice when gateway is in sandbox/test mode.
	 */
	public function sandbox_admin_notice()
	{
		if ('yes' !== $this->gateway->enabled) {
			return;
		}
		
		// Only show on this gateway's settings page.
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reading URL parameters for conditional notice display.
		$page = isset($_GET['page']) ? sanitize_text_field(wp_unslash($_GET['page'])) : '';
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reading URL parameters for conditional notice display.
		$tab = isset($_GET['tab']) ? sanitize_text_field(wp_unslash($_GET['tab'])) : '';
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reading URL parameters for conditional notice display.
		$section = isset($_GET['section']) ? sanitize_text_field(wp_unslash($_GET['section'])) : '';
		
		if ('wc-settings' !== $page || 'checkout' !== $tab || $this->id !== $section) {
			return;
		}
		
		if ($this->gateway->testmode) {
			echo '<div class="notice notice-warning"><p>';
			printf(
				/* translators: %s: Gateway title */
				esc_html__('%s is currently in Sandbox mode. No real transactions will be processed.', 'authorize-net-payments-for-woocommerce'),
				'<strong>' . esc_html($this->gateway->title) . '</strong>'
			);
			echo '</p></div>';
		}
	}
	
	/**
	 * Handles Refund from Admin Page.
	 *
	 * @param int    $order_id Order ID.
	 * @param string|null $amount Amount of Refund. If null, full refundable amount is used.
	 *
	 * @return WP_Error|mixed Refund or void result.
	 */
	public function process_refund($order_id, $amount = null)
	{
		$order = wc_get_order($order_id);
		if (is_wp_error($order) || ! $order) {
			return new WP_Error('invalid_order', __('Invalid order.', 'authorize-net-payments-for-woocommerce'));
		}
		$order_status = $order->get_status();
		// If order is cancelled, do not allow void.
		if (ANET_WOOCOMMERCE_ORDER_STATUS_CANCELLED === $order_status) {
			return new WP_Error('cannot_void_cancelled', __('Cannot void a cancelled order.', 'authorize-net-payments-for-woocommerce'));
		}
		// If order is refunded, do not allow refund.
		if (ANET_WOOCOMMERCE_ORDER_STATUS_REFUNDED === $order_status) {
			return new WP_Error('already_refunded', __('This order has already been refunded.', 'authorize-net-payments-for-woocommerce'));
		}
		$auth_transaction_id_credit_card = $this->get_order_meta($order, '_anet_credit_card_authorization_id');
		$charge_transaction_id_credit_card = $this->get_order_meta($order, '_anet_credit_card_charge_id');
		$capture_transaction_id_credit_card = $this->get_order_meta($order, '_anet_credit_card_capture_id');
		$charge_captured_credit_card = $this->get_order_meta($order, '_anet_credit_card_charge_captured');
		$refund_amount = $amount ? floatval($amount) : $order->get_total() - $order->get_total_refunded();
		if ($refund_amount <= 0) {
			return new WP_Error('invalid_refund_amount', __('Refund amount must be greater than zero.', 'authorize-net-payments-for-woocommerce'));
		}
		$refund_void_api = new Anet_Refund_Void_Api($this->gateway);
		if (! $this->is_order_captured($order)) {
			$result = $refund_void_api->void($auth_transaction_id_credit_card, $order_id);
			return $result;
		} else {
			$capture_transaction_id = ANET_YES === $charge_captured_credit_card ? $charge_transaction_id_credit_card : $capture_transaction_id_credit_card;
			return $refund_void_api->refund($capture_transaction_id, $order_id, $refund_amount);
		}
	}
	/**
	 * Checks whether order is captured or not.
	 *
	 * @param object $order order details.
	 */
	public function is_order_captured($order)
	{
		$charge_captured = $this->get_order_meta($order, '_anet_credit_card_capture_id');
		// If charge_captured is explicitly set.
		if (in_array($charge_captured, array(ANET_YES, 'partial'), true)) {
			return true;
		}
		// Fallback: check if transaction type is 'sale'.
		$transaction_type = $this->get_order_meta($order, 'transaction_type');
		if (ANET_TRANSACTION_TYPE_AUTH_CAPTURE === $transaction_type) {
			return true;
		}
		// Additional fallback: check payment status or gateway response.
		$payment_status = $order->get_status();
		if (ANET_WOOCOMMERCE_ORDER_STATUS_PROCESSING === $payment_status || ANET_WOOCOMMERCE_ORDER_STATUS_COMPLETED === $payment_status) {
			return true;
		}
		return false;
	}
	/**
	 * This method validates refunded/voided amount and returns boolean to represent whether to show/hide refund button.
	 *
	 * @param \WC_Order $order order details.
	 * @return bool
	 */
	public function validate_refund_amount(\WC_Order $order)
	{
		// Fetching Total amount.
		$total_amount  = $order->get_total();
		$refund_amount = '';
		// Fetching Array with all MetaData objects.
		$order_meta = $this->get_order_meta_data($order);
		$trans_exist = false;
		// Looping through the array.
		foreach ($order_meta as $om => $om_value) {
			$key = is_object($om_value) ? $om_value->get_data()['key'] : $om;
			$value = is_object($om_value) ? $om_value->get_data()['value'] : (is_array($om_value) ? end($om_value) : $om_value);
			// Checking if transaction id exists for void/refund.
			if ((str_contains($key, '_anet_credit_card_refund_id') && '' !== $value) || (str_contains($key, '_anet_credit_card_void_id') && '' !== $value)) {
				$trans_exist = true;
			}
			// Checking if any key contains void/refund amount.
			if ((str_contains($key, 'void_amount') || str_contains($key, 'refund_amount')) && ($order->has_status(ANET_WOOCOMMERCE_ORDER_STATUS_CANCELLED) || $order->has_status(ANET_WOOCOMMERCE_ORDER_STATUS_REFUNDED))) {
				$refund_amount = $value;
			}
		}
		// Return false to Refund Button Visibility.
		return ($total_amount == $refund_amount && $trans_exist) ? false : true; // phpcs:ignore
	}
	/**
	 * Register the JavaScript for the admin area.
	 *
	 * @param string $hook_suffix Hook URL.
	 */
	public function enqueue_scripts($hook_suffix)
	{
		if ('post.php' === $hook_suffix || 'woocommerce_page_wc-orders' === $hook_suffix) {
			// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Safe usage: only reading URL parameters for script loading determination
			$request_data = $_REQUEST;
			if (! empty($request_data['post'])) {
				$order = wc_get_order(wc_clean(wp_unslash($request_data['post'])));
				if (! $order) {
					return;
				}
			} elseif (! empty($request_data['id'])) {
				$order = wc_get_order(wc_clean(wp_unslash($request_data['id'])));
			} else {
				return;
			}
			if ($order->get_payment_method('edit') === $this->id || ANET_CREDIT_CARD_GATEWAY_ID === $order->get_payment_method('edit')) {
				$this->enqueue_edit_order_assets($order);
			}
		}
	}
	/**
	 * Enqueues the assets for the Edit Order screen.
	 *
	 * @param \WC_Order $order order object.
	 */
	public function enqueue_edit_order_assets(\WC_Order $order)
	{
		wp_enqueue_script('anet-admin-credit-card-order', plugin_dir_url(dirname(__FILE__)) . '../assets/js/admin/anet-admin.js', array('jquery'), ANET_PLUGIN_VERSION, true);
		wp_localize_script(
			'anet-admin-credit-card-order',
			'anet_admin_order',
			array(
				'ajax_url'                 => admin_url('admin-ajax.php'),
				'gateway_id'               => $order->get_payment_method('edit'),
				'order_id'                 => $order->get_id(),
				'capture_message'          => __('Are you sure you wish to process this capture? The action cannot be reversed.', 'authorize-net-payments-for-woocommerce'),
				'capture_action'           => 'anet_wc_capture_action',
				'capture_nonce'            => wp_create_nonce('anet_wc_capture_action'),
				'capture_error'            => __('Something went wrong, and the capture could no be completed. Please try again.', 'authorize-net-payments-for-woocommerce'),
				'refund_button_visibility' => $this->validate_refund_amount($order),
				'total_amount'             => $order->get_total(),
				'order_status'             => $order->get_status(),
				'total_refund_amount'      => $order->get_remaining_refund_amount(),
				'anet_credit_card_id'      => ANET_CREDIT_CARD_GATEWAY_ID,
				'anet_echeck_id'     		 	=>  ANET_ECHECK_GATEWAY_ID,
				'anet_order_status_hold'      	=> ANET_WOOCOMMERCE_ORDER_STATUS_ON_HOLD,
				'anet_order_status_processing'	=> ANET_WOOCOMMERCE_ORDER_STATUS_PROCESSING,
				'anet_order_status_completed'	=> ANET_WOOCOMMERCE_ORDER_STATUS_COMPLETED,
				'anet_val_undefined'     	    => ANET_VAL_UNDEFINED,
				'anet_order_status_refunded'	=> ANET_WOOCOMMERCE_ORDER_STATUS_REFUNDED,
				'anet_order_status_cancelled'	=> ANET_WOOCOMMERCE_ORDER_STATUS_CANCELLED
			)
		);
	}
}
add_action('admin_enqueue_scripts', function () {
	// Verify we're in the admin area and user has proper capabilities.
	if (!is_admin() || !current_user_can('manage_woocommerce')) { // phpcs:ignore WordPress.WP.Capabilities.Unknown
		return;
	}
	// Safely check URL parameters for conditional script loading.
	// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reading URL parameters for admin script loading, not processing form data.
	$page = isset($_GET['page']) ? sanitize_text_field(wp_unslash($_GET['page'])) : '';
	// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reading URL parameters for admin script loading, not processing form data.
	$action = isset($_GET['action']) ? sanitize_text_field(wp_unslash($_GET['action'])) : '';
	if (
		'wc-orders--shop_subscription' === $page &&
		'edit' === $action
	) {
		wp_enqueue_script(
			'anet-admin-credit-card-order',
			plugin_dir_url(dirname(__FILE__)) . '../assets/js/admin/anet-admin.js',
			array('jquery'),
			ANET_PLUGIN_VERSION,
			true
		);
	}
});
