<?php

namespace DigitalApps\PaymentsForAdyen\Admin;

defined('ABSPATH') || exit;

/**
 * Admin class for Digital Apps Payments for Adyen
 */
class Admin
{
	/**
	 * Constructor: register admin hooks
	 */
	public function __construct()
	{
		add_action('admin_menu', [$this, 'add_menu_page']);
		add_action('admin_enqueue_scripts', [$this, 'enqueue_assets']);
		add_filter(
			'plugin_action_links_' . plugin_basename(DIGITALAPPS_PAYMENTS_FOR_ADYEN_PLUGIN_FILE),
			[$this, 'add_plugin_action_links']
		);
		// Hook for adding custom actions to the single order page dropdown
		add_filter('woocommerce_order_actions', [$this, 'add_capture_action_to_order_dropdown']);
		// WooCommerce native action handler for the capture action
		add_action('woocommerce_order_action_digitalapps_payments_for_adyen_capture', [$this, 'process_adyen_capture_action']);
		add_action('woocommerce_order_action_digitalapps_payments_for_adyen_cancel', [$this, 'process_adyen_cancel_action']);
		add_action('woocommerce_order_action_digitalapps_payments_for_adyen_reverse', [$this, 'process_adyen_reversal_action']);
	}

	/**
	 * Add a contextual Pro upgrade link to the plugin row.
	 *
	 * @param array $actions Existing plugin action links.
	 * @return array Modified plugin action links.
	 */
	public function add_plugin_action_links($actions)
	{
		if (defined('DIGITALAPPS_PAYMENTS_FOR_ADYEN_PRO_ACTIVE') && DIGITALAPPS_PAYMENTS_FOR_ADYEN_PRO_ACTIVE) {
			return $actions;
		}

		$upgrade_url = apply_filters(
			'digitalapps_payments_for_adyen_upgrade_url',
			add_query_arg(
				[
					'utm_source' => 'wordpress',
					'utm_medium' => 'plugin',
					'utm_campaign' => 'adyen_payments_pro',
					'utm_content' => 'plugins_page_upgrade_link',
				],
				'https://digitalapps.com/wordpress-plugins/wp-adyen-payments/'
			)
		);

		$upgrade_link = sprintf(
			'<a href="%1$s" style="color: #008a20; font-weight: 600;" aria-label="%2$s">%3$s</a>',
			esc_url($upgrade_url),
			esc_attr__('Upgrade Digital Apps Payments for Adyen to Pro', 'digital-apps-payments-for-adyen'),
			esc_html__('Upgrade to Pro', 'digital-apps-payments-for-adyen')
		);

		return ['digitalapps_payments_for_adyen_upgrade' => $upgrade_link] + $actions;
	}

	/**
	 * Add plugin admin menu page
	 */
	public function add_menu_page()
	{
		add_menu_page(
			__('Digital Apps Payments for Adyen', 'digital-apps-payments-for-adyen'),
			__('Digital Apps Payments', 'digital-apps-payments-for-adyen'),
			'manage_woocommerce',
			'digital-apps-payments-for-adyen',
			[$this, 'render_admin_page'],
			'dashicons-money-alt'
		);
	}

	/**
	 * Enqueue React app assets in admin
	 *
	 * @param string $hook_suffix
	 */
	public function enqueue_assets($hook_suffix)
	{
		// Enqueue assets for the plugin's admin page
		if ($hook_suffix === 'toplevel_page_digital-apps-payments-for-adyen') {
			$js_path = DIGITALAPPS_PAYMENTS_FOR_ADYEN_PATH . 'build/admin/main.js';

			wp_enqueue_script(
				'digitalapps-payments-for-adyen-admin',
				DIGITALAPPS_PAYMENTS_FOR_ADYEN_URL . 'build/admin/main.js',
				['wp-element', 'wp-i18n', 'wp-api-fetch'],
				file_exists($js_path) ? filemtime($js_path) : false,
				true
			);

			// Localize settings REST endpoint and nonce
			wp_localize_script('digitalapps-payments-for-adyen-admin', 'DigitalAppsPaymentsForAdyenSettings', [
				'root'        => esc_url_raw(rest_url('digitalapps-payments-for-adyen/v1/')),
				'nonce'       => wp_create_nonce('wp_rest'),
				'loggingUrl'  => esc_url_raw(admin_url('admin.php?page=wc-status&tab=logs')),
				'paymentsUrl' => esc_url_raw(admin_url('admin.php?page=wc-settings&tab=checkout')),
			]);

			wp_set_script_translations(
				'digitalapps-payments-for-adyen-admin',
				'digital-apps-payments-for-adyen'
			);
		}
	}

	/**
	 * Render the admin page container
	 */
	public function render_admin_page()
	{
		echo '<div class="wrap digitalappsPaymentsAdmin"><div id="digitalapps-payments-for-adyen-admin-app"></div></div>';
	}

	/**
	 * Add custom actions to WooCommerce order page.
	 *
	 * Add custom actions to WooCommerce order page dropdown.
	 *
	 * @param array $actions Existing actions.
	 * @return array Modified actions.
	 */
	public function add_capture_action_to_order_dropdown($actions)
	{
		global $theorder; // Get the current order object in the admin context

		if (!$theorder) {
			return $actions;
		}

		$logger = new \DigitalApps\PaymentsForAdyen\Logger();
		$settings = get_option('digitalapps_payments_for_adyen_settings', []);
		$capture_mode = (string) $theorder->get_meta('_digitalapps_payments_for_adyen_capture_mode', true);
		if (!in_array($capture_mode, ['automatic', 'manual'], true)) {
			$capture_mode = $settings['captureMode'] ?? 'automatic';
		}

		$logger->log('DEBUG', ['message' => 'add_capture_action_to_order_dropdown called for order', 'order_id' => $theorder->get_id()]);
		$logger->log('DEBUG', ['message' => 'Capture Mode', 'capture_mode' => $capture_mode]);
		$logger->log('DEBUG', ['message' => 'Order needs payment', 'needs_payment' => $theorder->needs_payment()]);
		$logger->log('DEBUG', ['message' => 'Order payment method', 'payment_method' => $theorder->get_payment_method()]);
		$logger->log('DEBUG', ['message' => 'Order status', 'status' => $theorder->get_status()]);

		// Check if manual capture is enabled and order is eligible
		// An order on-hold with Adyen payment method and a PSP reference is eligible for manual capture.
		if ('manual' === $capture_mode && $theorder->get_payment_method() === 'digitalapps_payments_for_adyen_card' && $theorder->get_status() === 'on-hold') {
			$logger->log('DEBUG', ['message' => 'Initial conditions met for order', 'order_id' => $theorder->get_id()]);
			// Check if the order has a PSP reference (meaning it was authorized by Adyen)
			$psp_reference = $theorder->get_transaction_id(); // WooCommerce stores PSP reference as transaction ID
			$logger->log('DEBUG', ['message' => 'PSP Reference', 'psp_reference' => $psp_reference]);

			if ($psp_reference) { // Only need PSP reference, status is already checked
				$logger->log('DEBUG', ['message' => 'All conditions met, adding capture action for order', 'order_id' => $theorder->get_id()]);
				$actions['digitalapps_payments_for_adyen_capture'] = __('Capture Adyen Payment', 'digital-apps-payments-for-adyen');
				$cancel_operation = \DigitalApps\PaymentsForAdyen\Adyen_Operation::get($theorder, 'cancel:authorization');
				if (!in_array($cancel_operation['status'] ?? '', ['initiated', 'succeeded'], true)) {
					$actions['digitalapps_payments_for_adyen_cancel'] = __('Cancel Adyen Authorization', 'digital-apps-payments-for-adyen');
				}
			} else {
				$logger->log('DEBUG', ['message' => 'PSP reference not found for order', 'order_id' => $theorder->get_id(), 'psp_reference' => $psp_reference]);
			}
		} else {
			$logger->log('DEBUG', ['message' => 'Initial conditions not met for order', 'order_id' => $theorder->get_id(), 'capture_mode' => $capture_mode, 'payment_method' => $theorder->get_payment_method(), 'status' => $theorder->get_status()]);
		}

		if (
			$theorder->get_payment_method() === 'digitalapps_payments_for_adyen_card'
			&& $theorder->get_transaction_id()
			&& $theorder->is_paid()
			&& !$theorder->has_status(['cancelled', 'refunded'])
		) {
			$reversal = \DigitalApps\PaymentsForAdyen\Adyen_Operation::get($theorder, 'reversal:full');
			if (!in_array($reversal['status'] ?? '', ['initiated', 'succeeded'], true)) {
				$actions['digitalapps_payments_for_adyen_reverse'] = __('Cancel or Refund Adyen Payment', 'digital-apps-payments-for-adyen');
			}
		}

		return $actions;
	}

	/**
	 * Process the custom order action for capturing payment.
	 *
	 * @param \WC_Order $order The WooCommerce order object.
	 */
	public function process_adyen_capture_action($order)
	{
		$logger = new \DigitalApps\PaymentsForAdyen\Logger();
		$order_id = $order->get_id();

		$logger->log('DEBUG', ['message' => 'process_adyen_capture_action called', 'order_id' => $order_id]);

		// Ensure the order is eligible for capture
		if ($order->get_status() !== 'on-hold' || $order->get_payment_method() !== 'digitalapps_payments_for_adyen_card') {
			$order->add_order_note(__('Adyen payment capture failed: Order is not eligible for manual capture.', 'digital-apps-payments-for-adyen'));
			$logger->log('ERROR', ['message' => 'Order not eligible for manual capture', 'order_id' => $order_id, 'status' => $order->get_status(), 'payment_method' => $order->get_payment_method()]);
			return; // Exit without further processing
		}

		$psp_reference = $order->get_transaction_id();
		if (empty($psp_reference)) {
			$order->add_order_note(__('Adyen payment capture failed: Adyen PSP Reference not found for this order.', 'digital-apps-payments-for-adyen'));
			$logger->log('ERROR', ['message' => 'PSP Reference not found for order', 'order_id' => $order_id]);
			return; // Exit without further processing
		}

		$amount = $order->get_total();
		$currency = $order->get_currency();
		$operation_id = 'capture:full';
		$existing_operation = \DigitalApps\PaymentsForAdyen\Adyen_Operation::get($order, $operation_id);
		if (in_array($existing_operation['status'] ?? '', ['initiated', 'succeeded'], true)) {
			$order->add_order_note(__('Adyen manual capture was not repeated because an existing request is awaiting or has received webhook confirmation.', 'digital-apps-payments-for-adyen'));
			return;
		}
		$idempotency_key = \DigitalApps\PaymentsForAdyen\Adyen_Operation::key_for_order($order, $operation_id);

		$logger->log('DEBUG', ['message' => 'Attempting Adyen capture', 'order_id' => $order_id, 'psp_reference' => $psp_reference, 'amount' => $amount, 'currency' => $currency]);

		$adyen_client = \DigitalApps\PaymentsForAdyen\Adyen_Client::for_order($order);
		$response = $adyen_client->capture($psp_reference, $amount, $currency, $idempotency_key);

		if (isset($response['status']) && $response['status'] === 'received') {
			\DigitalApps\PaymentsForAdyen\Adyen_Operation::mark($order, $operation_id, 'initiated', [
				'type' => 'capture',
				'pspReference' => sanitize_text_field($response['pspReference'] ?? ''),
				'originalReference' => $psp_reference,
			]);
			// Do NOT call $order->payment_complete() here.
			// Rely on Adyen webhook to update the order status for accuracy.
			/* translators: %s: Adyen PSP reference. */
			$order->add_order_note(sprintf(__('Adyen manual capture request sent. PSP Reference: %s. Awaiting webhook confirmation for status update.', 'digital-apps-payments-for-adyen'), $response['pspReference'] ?? $psp_reference));
			// Keep order status as 'on-hold' until webhook confirms.
			$order->save(); // Save the order note.
			$logger->log('INFO', ['message' => 'Adyen manual capture request sent, awaiting webhook confirmation', 'order_id' => $order_id, 'psp_reference' => $psp_reference]);
		} else {
			$order->add_order_note(__('Adyen manual capture request was not accepted. Review the protected WooCommerce logs before retrying.', 'digital-apps-payments-for-adyen'));
			$logger->log('ERROR', ['message' => 'Payment capture request failed via WooCommerce action', 'order_id' => $order_id, 'response' => $response]);
		}
	}

	/** Request cancellation of a confirmed uncaptured authorization. */
	public function process_adyen_cancel_action($order)
	{
		if (
			!$order
			|| 'digitalapps_payments_for_adyen_card' !== $order->get_payment_method()
			|| !$order->has_status('on-hold')
			|| !$order->get_transaction_id()
		) {
			return;
		}

		$this->initiate_order_modification(
			$order,
			'cancel:authorization',
			'cancel',
			__('Adyen cancellation request accepted. Awaiting webhook confirmation.', 'digital-apps-payments-for-adyen')
		);
	}

	/** Request a race-safe reversal for a paid payment. */
	public function process_adyen_reversal_action($order)
	{
		if (
			!$order
			|| 'digitalapps_payments_for_adyen_card' !== $order->get_payment_method()
			|| !$order->is_paid()
			|| !$order->get_transaction_id()
			|| $order->has_status(['cancelled', 'refunded'])
		) {
			return;
		}

		$this->initiate_order_modification(
			$order,
			'reversal:full',
			'reverse',
			__('Adyen reversal request accepted. Awaiting cancel-or-refund webhook confirmation.', 'digital-apps-payments-for-adyen')
		);
	}

	/** Initiate one duplicate-protected cancellation or reversal. */
	private function initiate_order_modification($order, $operation_id, $method, $success_note)
	{
		$existing = \DigitalApps\PaymentsForAdyen\Adyen_Operation::get($order, $operation_id);
		if (in_array($existing['status'] ?? '', ['initiated', 'succeeded'], true)) {
			$order->add_order_note(__('Adyen modification was not repeated because an existing request is pending or complete.', 'digital-apps-payments-for-adyen'));
			return;
		}

		$idempotency_key = \DigitalApps\PaymentsForAdyen\Adyen_Operation::key_for_order($order, $operation_id);
		$client = \DigitalApps\PaymentsForAdyen\Adyen_Client::for_order($order);
		$response = $client->{$method}($order->get_transaction_id(), $idempotency_key);
		if ('received' === ($response['status'] ?? '')) {
			\DigitalApps\PaymentsForAdyen\Adyen_Operation::mark($order, $operation_id, 'initiated', [
				'type' => $method,
				'pspReference' => sanitize_text_field($response['pspReference'] ?? ''),
				'originalReference' => $order->get_transaction_id(),
			]);
			$order->add_order_note($success_note);
			return;
		}

		$order->add_order_note(__('Adyen did not accept the modification request. Review the protected WooCommerce logs before retrying.', 'digital-apps-payments-for-adyen'));
		(new \DigitalApps\PaymentsForAdyen\Logger())->log('ERROR', [
			'message' => 'Adyen order modification request failed',
			'order_id' => $order->get_id(),
			'operation' => $method,
			'response' => $response,
		]);
	}

}
