<?php
/**
 * @package     Splitit_WooCommerce_Plugin
 *
 * File - create-log-table.php
 * Function for create checkout data table
 */

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

require_once dirname( __DIR__ ) . '/classes/class-splitit-flexfields-payment-plugin-log.php';

// daily cron job.
if ( ! wp_next_scheduled( 'check_splitit_refund_status_daily' ) ) {
	wp_schedule_event( time(), 'daily', 'check_splitit_refund_status_daily' );
}
add_action( 'check_splitit_refund_status_daily', 'check_splitit_refund_status_by_ipn_daily' );

function check_splitit_refund_status_by_ipn_daily() {
	$log_data = array(
		'user_id' => null,
		'method'  => __( 'check_splitit_refund_status_by_ipn_daily() Splitit', 'splitit-installment-payments' ),
	);

	SplitIt_FlexFields_Payment_Plugin_Log::save_log_info( $log_data, 'check_splitit_refund_status_by_ipn_daily() - daily cron job processing', 'info' );

	try {
		$orders_waiting_refund = SplitIt_FlexFields_Payment_Plugin_Log::select_from_refund_log_orders_without_refund_result();

		global $settings_for_check_refund;

		foreach ( $orders_waiting_refund as $item ) {
			// info from DB.
			$entity_id         = $item->id;
			$ipn               = $item->ipn;
			$order_id          = $item->order_id;
			$splitit_refund_id = $item->refund_id;
			$refund_amount     = $item->refund_amount;

			// info from Splitit.
			$api = new SplitIt_FlexFields_Payment_Plugin_API( $settings_for_check_refund );
			try {
				$ipn_info = $api->get_ipn_info( $ipn );
			} catch ( \Exception $e ) {
				SplitIt_FlexFields_Payment_Plugin_Log::update_refund_log( $entity_id, array( 'action_type' => 'done' ) );
				$order_with_failed_refund = wc_get_order( $order_id );
				if ( $order_with_failed_refund ) {
					$order_with_failed_refund->add_order_note( 'Refund failed by Splitit. Installments Plan Number not found in Splitit Merchant Hub. For more details please contact the Splitit Support Team' );
				}
				throw new Exception( 'Exception in check_splitit_refund_status_by_ipn_daily(): ' . esc_html( $e->getMessage() ) );
			}

			SplitIt_FlexFields_Payment_Plugin_Log::save_log_info( $log_data, 'check_splitit_refund_status_by_ipn_daily() - IPN info: ' . json_encode( $ipn_info ), 'info' );

			$ipn_status = $ipn_info->getStatus();

			$ipn_info_refunds = $ipn_info->getRefunds();
			$order            = wc_get_order( $order_id );

			if ( ! $order ) {
				SplitIt_FlexFields_Payment_Plugin_Log::update_refund_log( $entity_id, array( 'action_type' => 'done' ) );
				throw new Exception( 'Refund cron job error. There is no order with ID = ' . $order_id . ' in platform. IPN = ' . $ipn . '' );
			}

			$time_difference          = time() - strtotime( $item->updated_at );
			$fourteen_days_in_seconds = 14 * 24 * 60 * 60;

			// checking whether it has been more than 14 days since the recording.
			if ( $time_difference > $fourteen_days_in_seconds ) {
				SplitIt_FlexFields_Payment_Plugin_Log::update_refund_log( $entity_id, array( 'action_type' => 'done' ) );
			}

			if ( $ipn_info->getRefOrderNumber() == $order_id ) {
				if ( ! empty( $ipn_info_refunds ) ) {

					foreach ( $ipn_info_refunds as $splitit_refund ) {
						$refund_id = $splitit_refund->getRefundId();

						if ( $refund_id == $splitit_refund_id ) {
							$refund_status = $splitit_refund->getStatus();

							$splitit_refund_amount = $splitit_refund->getTotalAmount();

							if ( 'Succeeded' == $refund_status ) {
								// this is for the case if the status is Succeeded, but for some reason the webhook did not arrive and
								// the order status on the platform has not yet been changed to Refunded or Cancelled.

								if ( $splitit_refund_amount == $refund_amount ) {

									if ( 'refund' == $item->action_type ) {
										$refunds = $order->get_refunds();

										if ( ( empty( $refunds ) || $order->get_remaining_refund_amount() > 0 ) && in_array( $order->get_status(), array( 'processing', 'completed' ) ) ) {

											$reason = 'splitit_programmatically';

											if ( $order->get_remaining_refund_amount() >= $refund_amount ) {
												$refund = wc_create_refund(
													array(
														'amount'   => $refund_amount,
														'reason'   => $reason,
														'order_id' => $order_id,
														'refund_payment' => true,
													)
												);

												SplitIt_FlexFields_Payment_Plugin_Log::update_refund_log( $entity_id, array( 'action_type' => 'done' ) );

												if ( is_wp_error( $refund ) ) {
													if ( 'Invalid refund amount.' == $refund->get_error_message() ) {
														$order->add_order_note( 'Refund failed by Splitit: Refund requested amount = ' . $refund_amount . ' exceeds remaining order balance of ' . $order->get_remaining_refund_amount() );
														SplitIt_FlexFields_Payment_Plugin_Log::save_log_info( $log_data, 'check_splitit_refund_status_by_ipn_daily() - Refund requested amount = ' . $refund_amount . ' exceeds remaining order balance of ' . $order->get_remaining_refund_amount() . '; Order ID: ' . $order_id . ', ipn = ' . $ipn, 'error' );
													} else {
														$order->add_order_note( 'Refund failed by Splitit. Amount: ' . $refund_amount . ';Error: ' . $refund->get_error_message() );
														SplitIt_FlexFields_Payment_Plugin_Log::save_log_info( $log_data, 'check_splitit_refund_status_by_ipn_daily() - Refund error: ' . $refund->get_error_message() . '; Amount: ' . $refund_amount . '; Order ID: ' . $order_id . ', ipn = ' . $ipn, 'error' );
													}
												} else {
													SplitIt_FlexFields_Payment_Plugin_Log::update_refund_log( $entity_id, array( 'action_type' => 'done' ) );
													$order->add_order_note( 'A refund for the amount = ' . $refund_amount . ' has succeeded on the Splitit side.' );
													SplitIt_FlexFields_Payment_Plugin_Log::save_log_info( $log_data, 'check_splitit_refund_status_by_ipn_daily() - Refund success. Amount: ' . $refund_amount . ', Order ID: ' . $order_id . ' Refund ID: ' . $splitit_refund_id . ', ipn = ' . $ipn, 'info' );
												}
											} else {
												SplitIt_FlexFields_Payment_Plugin_Log::update_refund_log( $entity_id, array( 'action_type' => 'done' ) );
												$order->add_order_note( 'Splitit made a refund for a different amount = ' . $splitit_refund_amount . '; Check this order in the Merchant Portal or contact Splitit support.' );
												SplitIt_FlexFields_Payment_Plugin_Log::save_log_info( $log_data, 'check_splitit_refund_status_by_ipn_daily() - Refund requested amount = ' . $splitit_refund_amount . ' exceeds remaining order balance of ' . $order->get_remaining_refund_amount() . 'Order ID: ' . $order_id . ', ipn = ' . $ipn, 'error' );
											}
										} else {
											SplitIt_FlexFields_Payment_Plugin_Log::update_refund_log( $entity_id, array( 'action_type' => 'done' ) );
											SplitIt_FlexFields_Payment_Plugin_Log::save_log_info( $log_data, 'check_splitit_refund_status_by_ipn_daily() - Refund has already been completed for this order. Order ID: ' . $order_id . ', ipn = ' . $ipn, 'info' );
										}
									} elseif ( 'cancel' == $item->action_type ) {

										SplitIt_FlexFields_Payment_Plugin_Log::update_refund_log( $entity_id, array( 'action_type' => 'done' ) );
										$order->add_order_note( 'Cancel for the amount = ' . $splitit_refund_amount . ' is succeeded on the Splitit side' );
										SplitIt_FlexFields_Payment_Plugin_Log::save_log_info( $log_data, 'check_splitit_refund_status_by_ipn_daily() - Cancel success. Amount = ' . $splitit_refund_amount . ', Order ID: ' . $order_id . ' Refund ID: ' . $splitit_refund_id . ', ipn = ' . $ipn, 'info' );

										$order->update_status( 'cancelled' );
									}
								} else {

									SplitIt_FlexFields_Payment_Plugin_Log::update_refund_log( $entity_id, array( 'action_type' => 'done' ) );

									if ( 'Cleared' == $ipn_status && 0 == $splitit_refund_amount && 'Succeeded' == $refund_status ) {
										if ( 'refund' == $item->action_type ) {
											$order->add_order_note( 'Refund has already been completed for this order on Splitit side' );
											$order->update_status( 'cancelled' );
										} elseif ( 'cancel' == $item->action_type ) {
											$order->add_order_note( 'Cancel has already been completed for this order on Splitit side' );
											$order->update_status( 'cancelled' );
										}
									} else {
										$order->add_order_note( 'Refund order programmatically is failed, incorrect refund amount' );
										throw new Exception( 'Refund cron job error. Splitit made a refund for a different amount. Platform amount = ' . $refund_amount . ', and Splitit amount = ' . $splitit_refund_amount . '; Check this order in the Merchant Portal. IPN = ' . $ipn . '' );
									}
								}
							} elseif ( 'Failed' == $refund_status ) {

								SplitIt_FlexFields_Payment_Plugin_Log::update_refund_log( $entity_id, array( 'action_type' => 'done' ) );
								$order->add_order_note( 'Refund failed by Splitit. Refund status is Failed. For more details please contact the Splitit Support Team' );
								SplitIt_FlexFields_Payment_Plugin_Log::save_log_info( $log_data, 'check_splitit_refund_status_by_ipn_daily() - Refund failed by Splitit. Refund status from Splitit is Failed. Order ID = ' . $order_id . ', ipn = ' . $ipn, 'error' );

							} elseif ( 'Pending' == $refund_status ) {

								// checking whether it has been more than 14 days since the recording.
								if ( $time_difference > $fourteen_days_in_seconds ) {
									SplitIt_FlexFields_Payment_Plugin_Log::update_refund_log( $entity_id, array( 'action_type' => 'done' ) );
									$order->add_order_note( 'Refund failed by Splitit. Refund status is Pending. For more details please contact the Splitit Support Team' );
									SplitIt_FlexFields_Payment_Plugin_Log::save_log_info( $log_data, 'check_splitit_refund_status_by_ipn_daily() - Refund failed by Splitit. The status has not been changed from Pending for more than 14 days. Order ID = ' . $order_id . ', ipn = ' . $ipn, 'error' );
								}
							}
						}
					}
				}
			}
		}

		SplitIt_FlexFields_Payment_Plugin_Log::save_log_info( $log_data, 'check_splitit_refund_status_by_ipn_daily() - Number of checked refunds: ' . count( $orders_waiting_refund ), 'info' );

	} catch ( Exception $e ) {
		SplitIt_FlexFields_Payment_Plugin_Log::save_log_info( $log_data, 'check_splitit_refund_status_by_ipn_daily() - error: ' . $e->getMessage(), 'error' );
		$skip_domains = array(
			'my-wordpress-blog.local',
			'localhost',
			'127.0.0.1',
		);
		if ( ! in_array( DOMAIN, $skip_domains, true ) ) {
			send_slack_refund_notification( 'Check refunds cron job error: \n ' . html_entity_decode( $e->getMessage() ) . ' \n Domain: <' . URL . '|' . DOMAIN . '> \n Platform: Woocommerce' );
		}
	}
}
