<?php
/**
 * Handles the BNPL transactions.
 */

namespace Flo_Checkout\Gateways\BNPL;

use Exception;
use Flo_Checkout\Gateways\BNPL\Models\BNPL_Transaction;
use Northmill_Online_Shared_Checkout\Northmill_Online_Shared\Modules\Loggers\Log_Level_Enum;

/**
 * Class BNPL_Transactions
 */
class BNPL_Transactions {

	/**
	 * Checks the status of a transaction and updates the order accordingly.
	 *
	 * @param int    $order_id       The ID of the order.
	 * @param string $check_type     Optional. The type of check to perform. Default is 'cron'.
	 *
	 * @return ?BNPL_Transaction
	 */
	public static function check_transaction_status( int $order_id, string $check_type = 'cron' ): ?BNPL_Transaction {
		$order = wc_get_order( $order_id );
		if ( ! $order ) {
			BNPL_Settings::log(
				'Cannot find order to check transaction status for',
				array( 'order_id' => $order_id ),
				Log_Level_Enum::ERROR
			);
			return null;
		}

		$transaction_id = $order->get_meta( 'northmill_bnpl_transaction_id' );

		if ( ! $transaction_id ) {
			BNPL_Settings::log(
				'Transaction ID not found on order to check transaction status for',
				array( 'order_id' => $order_id ),
				Log_Level_Enum::ERROR
			);
			return null;
		}

		$transaction = BNPL_API::instance()->get_transaction( $transaction_id );

		if ( ! $transaction ) {
			BNPL_Settings::log(
				'Failed to get transaction from Northmill',
				array(
					'order_id'       => $order_id,
					'transaction_id' => $transaction_id,
				),
				Log_Level_Enum::ERROR
			);
			return null;
		}

		if ( 'unknown' === $transaction->get_status_text() ) {
			BNPL_Settings::log(
				'Got unknown transaction status from Northmill',
				array(
					'order_id'       => $order_id,
					'transaction_id' => $transaction->get_transaction_id(),
					'payment_id'     => $transaction->get_payment_id(),
					'status'         => $transaction->get_status(),
				),
				Log_Level_Enum::ERROR
			);
			return null;
		}

		// Maybe update the order meta with the transaction status.
		$old_order_transaction_status = $order->get_meta( 'northmill_bnpl_transaction_status' );

		if ( $old_order_transaction_status !== $transaction->get_status_text() ) {
			$order->update_meta_data( 'northmill_bnpl_transaction_status', $transaction->get_status_text() );
			$order->save();
		}

		// If the transaction status is completed and the order is not paid, mark the order as paid.
		if (
			'completed' === $transaction->get_status_text() &&
			! in_array( $order->get_status(), wc_get_is_paid_statuses(), true )
		) {
			BNPL_Settings::log(
				'Got PAID BNPL status from Northmill',
				array(
					'order_id'       => $order_id,
					'transaction_id' => $transaction->get_transaction_id(),
					'payment_id'     => $transaction->get_payment_id(),
				),
				Log_Level_Enum::INFO
			);

			$order->add_order_note(
				sprintf(
					// translators: %s is the BNPL transaction ID.
					__( 'Northmill BNPL - Payment confirmed - BNPL Transaction ID: %s', 'flo-checkout-plugin' ),
					$transaction->get_transaction_id()
				)
			);
			try {
				$order->set_transaction_id( $transaction->get_transaction_id() );
			} catch ( Exception $e ) {
				BNPL_Settings::log(
					'Failed to set transaction ID on order',
					array(
						'order_id'       => $order_id,
						'transaction_id' => $transaction->get_transaction_id(),
						'payment_id'     => $transaction->get_payment_id(),
						'status'         => $transaction->get_status(),
						'exception'      => $e,
					),
					Log_Level_Enum::ERROR
				);
			}
			$order->payment_complete();

			// If this check is performed via AJAX, empty the cart.
			if ( 'ajax' === $check_type ) {
				WC()->cart->empty_cart();
			}

			// If the BNPL transaction status is cancelled and the order is not already cancelled or failed, mark the order as cancelled.
			// TODO: Confirm whether we should mark the order as failed or cancelled.
		} elseif (
			'cancelled' === $transaction->get_status_text() &&
			! in_array( $order->get_status(), array( 'cancelled', 'failed' ), true )
		) {
			BNPL_Settings::log(
				'Got CANCELLED from Northmill',
				array(
					'order_id'       => $order_id,
					'transaction_id' => $transaction->get_transaction_id(),
					'payment_id'     => $transaction->get_payment_id(),
				),
				Log_Level_Enum::INFO
			);

			// On cron checks, we manually cancel the order.
			// On AJAX checks, the order will be cancelled by redirect to the cancel url.
			if ( 'cron' === $check_type ) {
				wc_add_notice(
					apply_filters(
						'woocommerce_order_cancelled_notice',
						__( 'Your order was cancelled.', 'woocommerce' )
					),
					apply_filters( 'woocommerce_order_cancelled_notice_type', 'notice' )
				);
				$order->update_status( 'cancelled' );
			}

			$order->add_order_note(
				sprintf(
					// translators: %s is the BNPL transaction ID.
					__( 'Northmill BNPL - Payment cancelled - BNPL Transaction ID: %s', 'flo-checkout-plugin' ),
					$transaction->get_transaction_id()
				)
			);
		}

		return $transaction;
	}
}
