<?php
/**
 * Klarna Payments v1 Push Notification Handler & Helper Functions
 *
 * This file contains:
 * 1. Klarna API helper functions (credentials, order status, capture)
 * 2. Push notification handler for Klarna order status updates
 * 3. Full order processing function
 *
 * This is called by Klarna via the merchant_urls.push URL specified during session creation.
 * Klarna sends POST requests to notify about order status changes.
 *
 * IMPORTANT: This handler performs full order processing (PDF generation, email sending, balance creation)
 * when the order is captured, similar to wpgv_klarna_success_page_shortcode.
 * It checks if order is already processed to avoid duplicate processing.
 */

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

/**
 * Helper function to get Klarna API credentials
 * @return array Credentials with merchant_id, shared_secret, api_url, mode
 */
if (!function_exists('wpgv_get_klarna_credentials')) {
	function wpgv_get_klarna_credentials()
	{
		$klarna_mode = get_option('wpgv_klarna_mode') ?: 'sandbox';

		if ($klarna_mode === 'live') {
			return array(
				'merchant_id' => get_option('wpgv_klarna_live_merchant_id'),
				'shared_secret' => get_option('wpgv_klarna_live_shared_secret'),
				'api_url' => 'https://api.klarna.com',
				'mode' => 'live'
			);
		}

		return array(
			'merchant_id' => get_option('wpgv_klarna_demo_merchant_id'),
			'shared_secret' => get_option('wpgv_klarna_demo_shared_secret'),
			'api_url' => 'https://api.playground.klarna.com',
			'mode' => 'sandbox'
		);
	}
}

/**
 * Helper function to check Klarna order status
 *
 * @param string $order_id Klarna order ID
 * @return array|false Order data or false on failure
 */
if (!function_exists('wpgv_check_klarna_order_status')) {
	function wpgv_check_klarna_order_status($order_id)
	{
		$credentials = wpgv_get_klarna_credentials();

		if (empty($credentials['merchant_id']) || empty($credentials['shared_secret'])) {
			error_log('Klarna: credentials not configured');
			return false;
		}

		// Klarna Order Management API endpoint
		$order_url = $credentials['api_url'] . '/ordermanagement/v1/orders/' . $order_id;

		$args = array(
			'headers' => array(
				'Authorization' => 'Basic ' . base64_encode($credentials['merchant_id'] . ':' . $credentials['shared_secret']),
				'Content-Type' => 'application/json'
			),
			'timeout' => 30,
		);

		$response = wp_remote_get($order_url, $args);

		if (is_wp_error($response)) {
			error_log('Klarna: API request failed - ' . $response->get_error_message());
			return false;
		}

		$code = wp_remote_retrieve_response_code($response);
		$body = wp_remote_retrieve_body($response);
		$data = json_decode($body, true);

		if ($code >= 200 && $code < 300 && !empty($data)) {
			return $data;
		}

		error_log('Klarna: failed to get order status - HTTP ' . $code . ' - ' . $body);
		return false;
	}
}

/**
 * Capture a Klarna order (collect the authorized payment)
 *
 * @param string $klarna_order_id Klarna order ID
 * @param array $klarna_order Order data from wpgv_check_klarna_order_status (contains order_lines, amounts)
 * @return array Result with 'success', 'code', 'body', 'message' keys
 */
if (!function_exists('wpgv_klarna_capture_order')) {
	function wpgv_klarna_capture_order($klarna_order_id, $klarna_order = null)
	{
		if (empty($klarna_order_id)) {
			return array('success' => false, 'message' => 'Missing Klarna order ID');
		}

		$credentials = wpgv_get_klarna_credentials();
		if (empty($credentials['merchant_id']) || empty($credentials['shared_secret'])) {
			return array('success' => false, 'message' => 'Klarna credentials not configured');
		}

		// If order data not provided, fetch it
		if (empty($klarna_order)) {
			$klarna_order = wpgv_check_klarna_order_status($klarna_order_id);
			if (!$klarna_order) {
				return array('success' => false, 'message' => 'Could not retrieve Klarna order data');
			}
		}

		// Check if already captured
		$status = isset($klarna_order['status']) ? strtoupper($klarna_order['status']) : '';
		if (in_array($status, array('CAPTURED', 'PART_CAPTURED'))) {
			return array('success' => true, 'message' => 'Order already captured', 'already_captured' => true);
		}

		// Only AUTHORIZED orders can be captured
		if ($status !== 'AUTHORIZED') {
			return array('success' => false, 'message' => 'Order status is ' . $status . ', cannot capture');
		}

		// Build capture URL
		$api_base = rtrim($credentials['api_url'], '/');
		$capture_url = $api_base . '/ordermanagement/v1/orders/' . rawurlencode($klarna_order_id) . '/captures';

		// Get amount and order_lines from klarna_order
		$captured_amount = isset($klarna_order['remaining_authorized_amount']) ? intval($klarna_order['remaining_authorized_amount']) : (isset($klarna_order['order_amount']) ? intval($klarna_order['order_amount']) : 0);
		$order_lines = isset($klarna_order['order_lines']) ? $klarna_order['order_lines'] : array();

		if ($captured_amount <= 0) {
			return array('success' => false, 'message' => 'Invalid capture amount');
		}

		// Build capture payload
		$payload = array(
			'captured_amount' => $captured_amount,
			'order_lines' => $order_lines,
		);

		$args = array(
			'headers' => array(
				'Authorization' => 'Basic ' . base64_encode($credentials['merchant_id'] . ':' . $credentials['shared_secret']),
				'Content-Type' => 'application/json',
			),
			'body' => wp_json_encode($payload),
			'timeout' => 30,
		);

		error_log('Klarna Capture: Attempting capture for order ' . $klarna_order_id . ' - Amount: ' . $captured_amount);

		$response = wp_remote_post($capture_url, $args);

		if (is_wp_error($response)) {
			error_log('Klarna Capture: API request failed - ' . $response->get_error_message());
			return array('success' => false, 'message' => $response->get_error_message());
		}

		$code = wp_remote_retrieve_response_code($response);
		$body = wp_remote_retrieve_body($response);
		$data = json_decode($body, true);

		// Klarna returns 201 Created on successful capture
		if ($code >= 200 && $code < 300) {
			error_log('Klarna Capture: Success for order ' . $klarna_order_id);
			return array(
				'success' => true,
				'code' => $code,
				'body' => $data,
				'message' => 'Captured successfully',
				'capture_id' => isset($data['capture_id']) ? $data['capture_id'] : null
			);
		}

		$error_msg = '';
		if (!empty($data['error_messages'])) {
			$error_msg = implode(', ', $data['error_messages']);
		} elseif (!empty($data['error_message'])) {
			$error_msg = $data['error_message'];
		} elseif (!empty($data['error_code'])) {
			$error_msg = $data['error_code'];
		} else {
			$error_msg = $body;
		}

		error_log('Klarna Capture: Failed for order ' . $klarna_order_id . ' - HTTP ' . $code . ' - ' . $error_msg);
		return array('success' => false, 'code' => $code, 'body' => $data ?: $body, 'message' => $error_msg);
	}
}

/**
 * Process a Klarna order after successful payment
 * This is similar to the logic in wpgv_klarna_success_page_shortcode
 *
 * @param int $voucher_id The voucher ID in giftvouchers_list
 * @param string $klarna_order_id Klarna order ID
 * @return bool True if processed successfully, false otherwise
 */
function wpgv_process_klarna_order_complete($voucher_id, $klarna_order_id) {
	global $wpdb;

	$voucher_table = $wpdb->prefix . 'giftvouchers_list';
	$setting_table = $wpdb->prefix . 'giftvouchers_setting';
	$invoice_setting_table = $wpdb->prefix . 'giftvouchers_invoice_settings';

	// Get voucher details
	$voucher_options = $wpdb->get_row($wpdb->prepare(
		"SELECT * FROM $voucher_table WHERE id = %d",
		$voucher_id
	));

	if (!$voucher_options) {
		error_log('Klarna Push: Voucher not found for ID=' . $voucher_id);
		return false;
	}

	// Check if already processed (check_send_mail != 'unsent' means already processed)
	if ($voucher_options->check_send_mail != 'unsent') {
		error_log('Klarna Push: Order already processed for voucher ID=' . $voucher_id);
		return true; // Already processed, nothing to do
	}

	// Get settings
	$setting_options = $wpdb->get_row("SELECT * FROM $setting_table WHERE id = 1");
	$invoice_options = $wpdb->get_row("SELECT * FROM $invoice_setting_table WHERE id = 1");
	$is_invoice_active = (is_object($invoice_options) && isset($invoice_options->is_invoice_active)) ? $invoice_options->is_invoice_active : 0;

	error_log('Klarna Push: Processing complete order for voucher ID=' . $voucher_id);

	try {
		// 1. Update payment status and generate PDF
		$wpdb->update(
			$voucher_table,
			array(
				'payment_status' => 'Paid',
				'voucheradd_time' => current_time('mysql')
			),
			array('id' => $voucher_id),
			array('%s', '%s'),
			array('%d')
		);

		// Refresh voucher_options
		$voucher_options = $wpdb->get_row($wpdb->prepare(
			"SELECT * FROM $voucher_table WHERE id = %d",
			$voucher_id
		));

		// Generate PDF if function exists
		if (function_exists('wpgv_generate_receipt_pdf_for_voucher')) {
			wpgv_generate_receipt_pdf_for_voucher($voucher_id);
		}

		// 2. Update Klarna-specific meta
		update_post_meta($voucher_id, 'wpgv_klarna_payment_status', 'CAPTURED');
		update_post_meta($voucher_id, 'wpgv_payment_status', 'Completed');
		update_post_meta($voucher_id, 'wpgv_klarna_captured_at', current_time('mysql'));
		update_post_meta($voucher_id, 'wpgv_klarna_processed_by', 'push_notification');

		// 3. Record activity to create the balance (THIS IS CRITICAL!)
		if (class_exists('WPGV_Gift_Voucher_Activity')) {
			WPGV_Gift_Voucher_Activity::record($voucher_id, 'firsttransact', $voucher_options->amount, 'Voucher payment received via Klarna (push notification).');
			error_log('Klarna Push: Activity recorded for voucher ID=' . $voucher_id . ' amount=' . $voucher_options->amount);
		} else {
			error_log('Klarna Push: WPGV_Gift_Voucher_Activity class not found!');
		}

		// 4. Send emails
		$wpgv_invoice_mail_enable = (get_option('wpgv_invoice_mail_enable') != '') ? get_option('wpgv_invoice_mail_enable') : 1;
		$email_settings = wpgv_get_email_settings();

		// Get attachments
		if (function_exists('wpgv_get_attachment_paths')) {
			$attachment_data = wpgv_get_attachment_paths($voucher_options, $is_invoice_active);
			$attachments = $attachment_data['attachments'];
		} else {
			$attachments = array();
		}

		// Setup email headers
		if (function_exists('wpgv_setup_email_headers')) {
			$headers = wpgv_setup_email_headers($setting_options);
		} else {
			$headers = array('Content-Type: text/html; charset=UTF-8');
		}

		$send_instantly = ($voucher_options->email_send_date_time == 'send_instantly') ? 'send_instantly' : '';
		$check_send_mail = $voucher_options->check_send_mail;

		// Send recipient email
		if (function_exists('wpgv_send_recipient_email')) {
			$recipient_data = array(
				'recipientemailsubject' => $email_settings['recipientemailsubject'],
				'recipientemailbody' => $email_settings['recipientemailbody'],
				'shipping_type' => $voucher_options->shipping_type,
				'shipping_email' => $voucher_options->shipping_email,
				'buying_for' => $voucher_options->buying_for,
				'setting_options' => $setting_options,
				'voucher_options' => $voucher_options,
				'check_send_mail' => $check_send_mail,
				'send_instantly' => $send_instantly,
				'email_send_date_time' => $voucher_options->email_send_date_time,
				'headers' => $headers,
				'attachments' => $attachments
			);
			wpgv_send_recipient_email($recipient_data);
		}

		// Send buyer email
		if (function_exists('wpgv_send_buyer_email')) {
			$buyer_data = array(
				'emailsubject' => $email_settings['emailsubject'],
				'emailbody' => $email_settings['emailbody'],
				'setting_options' => $setting_options,
				'voucher_options' => $voucher_options,
				'check_send_mail' => $check_send_mail,
				'headers' => $headers,
				'attachments' => $attachments
			);
			$mail_sent = wpgv_send_buyer_email($buyer_data);

			if ($mail_sent && function_exists('wpgv_send_admin_email')) {
				$admin_email_data = array(
					'setting_options' => $setting_options,
					'voucher_options' => $voucher_options,
					'voucher_item' => $voucher_id,
					'check_send_mail' => $check_send_mail,
					'send_instantly' => $send_instantly,
					'email_settings' => $email_settings,
					'attachments' => $attachments
				);
				wpgv_send_admin_email($admin_email_data);
			}
		}

		error_log('Klarna Push: Successfully processed voucher ID=' . $voucher_id);
		return true;

	} catch (Exception $e) {
		error_log('Klarna Push: Error processing voucher ID=' . $voucher_id . ' - ' . $e->getMessage());
		return false;
	}
}

function wpgv_klarna_push_notification_handler() {
	// Log request details for debugging
	error_log('Klarna Push: Request method: ' . $_SERVER['REQUEST_METHOD']);

	// Klarna sends POST with JSON body
	$input = file_get_contents('php://input');
	$data = json_decode($input, true);

	error_log('Klarna Push Notification received: ' . print_r($data, true));

	// Klarna may send order_id directly or in nested structure
	$klarna_order_id = '';
	if (!empty($data['order_id'])) {
		$klarna_order_id = sanitize_text_field($data['order_id']);
	} elseif (!empty($data['order']) && !empty($data['order']['order_id'])) {
		$klarna_order_id = sanitize_text_field($data['order']['order_id']);
	}

	// Also check for GET parameter (some Klarna flows include order_id in URL)
	if (empty($klarna_order_id) && !empty($_GET['order_id'])) {
		$klarna_order_id = sanitize_text_field($_GET['order_id']);
	}

	if (empty($klarna_order_id)) {
		error_log('Klarna Push: Missing order_id in request');
		http_response_code(400);
		wp_die('Missing order_id');
	}

	// Determine event type
	$event_type = '';
	if (!empty($data['event_type'])) {
		$event_type = sanitize_text_field($data['event_type']);
	} elseif (!empty($data['status'])) {
		$event_type = sanitize_text_field($data['status']);
	}

	error_log('Klarna Push: Event=' . $event_type . ' for order=' . $klarna_order_id);

	// Find voucher/item by Klarna order_id stored in post meta
	global $wpdb;
	$voucher_table = $wpdb->prefix . 'giftvouchers_list';
	$postmeta_table = $wpdb->postmeta;

	// Get voucher IDs that have this Klarna order_id in post meta
	// The klarna_order_id is stored using update_post_meta() in klarna-authorize.php
	$voucher_ids = $wpdb->get_col($wpdb->prepare(
		"SELECT post_id FROM $postmeta_table
		WHERE meta_key = 'wpgv_klarna_order_id'
		AND meta_value = %s",
		$klarna_order_id
	));

	if (empty($voucher_ids)) {
		error_log('Klarna Push: No voucher found for order_id=' . $klarna_order_id);
		// Return 200 OK anyway to stop Klarna from retrying
		http_response_code(200);
		wp_die('Order not found');
	}

	error_log('Klarna Push: Found ' . count($voucher_ids) . ' voucher(s) for order');

	foreach ($voucher_ids as $voucher_id) {
		$voucher_id = intval($voucher_id);

		// Check if voucher exists in giftvouchers_list
		$voucher_exists = $wpdb->get_var($wpdb->prepare(
			"SELECT id FROM $voucher_table WHERE id = %d",
			$voucher_id
		));

		if (!$voucher_exists) {
			error_log('Klarna Push: Voucher ID=' . $voucher_id . ' not found in giftvouchers_list');
			continue;
		}

		// Handle different event types
		// Reference: https://docs.klarna.com/payments/after-payments/order-management/
		$success_events = array(
			'FRAUD_RISK_ACCEPTED',
			'ORDER_AUTHORIZED',
			'ORDER_CAPTURED',
			'AUTHORIZED',
			'CAPTURED',
			'PART_CAPTURED'
		);

		$failed_events = array(
			'ORDER_CANCELLED',
			'ORDER_EXPIRED',
			'FRAUD_RISK_REJECTED',
			'CANCELLED',
			'EXPIRED'
		);

		if (in_array(strtoupper($event_type), $success_events)) {
			// For CAPTURED events, perform full order processing (PDF, email, balance)
			// For AUTHORIZED events, just update status (capture will be done by success page or separately)
			$captured_events = array('ORDER_CAPTURED', 'CAPTURED', 'PART_CAPTURED');

			if (in_array(strtoupper($event_type), $captured_events)) {
				// Full processing for captured orders
				wpgv_process_klarna_order_complete($voucher_id, $klarna_order_id);
			} else {
				// For AUTHORIZED events, just mark as paid but don't process fully yet
				// The success page or auto-capture will handle full processing
				$wpdb->update(
					$voucher_table,
					array('payment_status' => 'Paid'),
					array('id' => $voucher_id),
					array('%s'),
					array('%d')
				);
				update_post_meta($voucher_id, 'wpgv_payment_status', 'Completed');
				update_post_meta($voucher_id, 'wpgv_klarna_last_event', $event_type);
				update_post_meta($voucher_id, 'wpgv_klarna_last_push', current_time('mysql'));
				error_log('Klarna Push: Marked voucher ' . $voucher_id . ' as Paid (event: ' . $event_type . ') - awaiting capture for full processing');
			}

		} elseif (in_array(strtoupper($event_type), $failed_events)) {
			// Mark as failed
			$wpdb->update(
				$voucher_table,
				array('payment_status' => 'Failed'),
				array('id' => $voucher_id),
				array('%s'),
				array('%d')
			);
			update_post_meta($voucher_id, 'wpgv_payment_status', 'Failed');
			update_post_meta($voucher_id, 'wpgv_klarna_last_event', $event_type);
			update_post_meta($voucher_id, 'wpgv_klarna_last_push', current_time('mysql'));
			error_log('Klarna Push: Marked voucher ' . $voucher_id . ' as Failed (event: ' . $event_type . ')');

		} else {
			// Unknown event - just log it
			update_post_meta($voucher_id, 'wpgv_klarna_last_event', $event_type);
			update_post_meta($voucher_id, 'wpgv_klarna_last_push', current_time('mysql'));
			error_log('Klarna Push: Unknown event type "' . $event_type . '" for voucher ' . $voucher_id);
		}
	}

	// Return 200 OK to acknowledge receipt
	// This tells Klarna not to retry the notification
	http_response_code(200);
	wp_die('OK');
}

add_action('wp_ajax_nopriv_wpgv_klarna_push_notification', 'wpgv_klarna_push_notification_handler');
add_action('wp_ajax_wpgv_klarna_push_notification', 'wpgv_klarna_push_notification_handler');
