<?php
/**
 * @package     Splitit_WooCommerce_Plugin
 *
 * File - class-splitit-flexfields-payment-plugin-log.php
 * Class for loggin user actions and transactions
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit; // @Exit if accessed directly
}

/**
 * Class SplitIt_FlexFields_Payment_Plugin_Log
 */
class SplitIt_FlexFields_Payment_Plugin_Log {
	/**
	 * @var string
	 */
	protected static $file_log = 'splitit.log';

	/**
	 * @var string
	 */
	protected static $db_table_log = 'splitit_log';

	/**
	 * @var string
	 */
	protected static $db_table_refund_info_log = 'splitit_async_refund_log';

	/**
	 * @var string
	 */
	protected static $db_table_transaction_log = 'splitit_transactions_log';

	/**
	 * @var string
	 */
	protected static $db_order_data = 'splitit_order_data_with_ipn';

	/**
	 * Log into DB, file and WC
	 *
	 * @param array  $data Data.
	 * @param string $message Message.
	 * @param string $type Type.
	 * @param null   $file File.
	 */
	public static function save_log_info( $data, $message, $type = '', $file = null ) {
		$data['message'] = $message;
		self::log_to_db( $data );
		self::wc_log( $type, $message );
	}

	/**
	 * Log to DB method
	 *
	 * @param array $data Data.
	 */
	public static function log_to_db( $data ) {
		global $wpdb;
		$table_name = $wpdb->prefix . self::$db_table_log;

		$user_id = ! empty( $data['user_id'] ) && (int) $data['user_id'] > 0
			? (int) $data['user_id']
			: null;

		$wpdb->insert(
			"$table_name",
			array(
				'user_id' => $user_id,
				'method'  => $data['method'] ?? null,
				'message' => $data['message'] ?? null,
				'date'    => gmdate( 'Y-m-d H:i:s' ),
			)
		);
	}

	/**
	 * Log refund info to DB method
	 *
	 * @param array $data Data.
	 */
	public static function save_refund_info( $data ) {
		global $wpdb;
		$table_name = $wpdb->prefix . self::$db_table_refund_info_log;

		if ( isset( $data['user_id'] ) && 0 === (int) $data['user_id'] ) {
			$data['user_id'] = null;
		}

		$wpdb->insert(
			"$table_name",
			array(
				'user_id'       => $data['user_id'] ?? null,
				'order_id'      => $data['order_id'] ?? null,
				'ipn'           => $data['ipn'] ?? null,
				'refund_id'     => $data['refund_id'] ?? null,
				'refund_amount' => $data['refund_amount'] ?? null,
				'refund_reason' => $data['refund_reason'] ?? null,
				'action_type'   => $data['action_type'] ?? null,
				'updated_at'    => gmdate( 'Y-m-d H:i:s' ),
			)
		);
	}

	/**
	 * WooCommerce log
	 *
	 * @param string $type Type.
	 * @param string $message Message.
	 * @param array  $context Context.
	 */
	public static function wc_log( $type, $message, $context = array() ) {
		$log = new WC_Logger();

		switch ( $type ) {
			case 'error':
				$log->error( $message, $context );
				break;
			case 'warning':
				break;
			case 'notice':
				$log->notice( $message, $context );
				break;
			case 'info':
				$log->info( $message, $context );
				break;
			case 'critical':
				$log->critical( $message, $context );
				break;
			case 'alert':
				$log->alert( $message, $context );
				break;
			case 'emergency':
				$log->emergency( $message, $context );
				break;
			default:
				$log->info( $message, $context );
				break;
		}
	}

	/**
	 * Method for adding data to transaction log
	 *
	 * @param array $data Data.
	 */
	public static function transaction_log( $data ) {
		global $wpdb;
		$table_name = $wpdb->prefix . self::$db_table_transaction_log;

		$user_id = ! empty( $data['user_id'] ) && (int) $data['user_id'] > 0
			? (int) $data['user_id']
			: null;

		$result = $wpdb->insert(
			"$table_name",
			array(
				'user_id'                 => $user_id,
				'order_id'                => $data['order_id'] ?? null,
				'installment_plan_number' => $data['installment_plan_number'] ?? null,
				'number_of_installments'  => $data['number_of_installments'] ?? null,
				'processing'              => $data['processing'] ?? null,
				'plan_create_succeed'     => $data['plan_create_succeed'] ?? 0,
				'date'                    => gmdate( 'Y-m-d H:i:s' ),
			)
		);

		if ( false === $result ) {
			$error_message = ! empty( $wpdb->last_error )
				? $wpdb->last_error
				: 'unknown DB error';
			self::save_log_info(
				array(
					'user_id' => $user_id,
					'method'  => __( 'splitit_flexfields_payment_plugin_transaction_log() Splitit', 'splitit-installment-payments' ),
				),
				'splitit_flexfields_payment_plugin_transaction_log insert failed: ' . $error_message,
				'error'
			);
		}
	}

	/**
	 * Method for updating transaction record
	 *
	 * @param array $data Data.
	 */
	public static function update_transaction_log( $data ) {
		global $wpdb;
		$table_name = $wpdb->prefix . self::$db_table_transaction_log;
		$wpdb->update( "$table_name", array( 'plan_create_succeed' => 1 ), array( 'installment_plan_number' => $data['installment_plan_number'] ) );
	}

	/**
	 * Method for updating refund record
	 *
	 * @param int   $id ID.
	 * @param array $data Data.
	 */
	public static function update_refund_log( $id, $data ) {
		global $wpdb;
		$table_name = $wpdb->prefix . self::$db_table_refund_info_log;

		$wpdb->update(
			$table_name,
			array(
				'action_type' => $data['action_type'],
			),
			array( 'id' => $id )
		);

		$log_data = array(
			'user_id' => null,
			'method'  => 'update_refund_log() Splitit',
		);

		if ( $wpdb->last_error ) {
			self::save_log_info( $log_data, 'update_refund_log() - Error when update refund_log: ' . $wpdb->last_error, 'error' );
		}
	}

	/**
	 * Get record from transaction log by ipn
	 *
	 * @param string $ipn Installment plun number.
	 * @param string $refund_id Refund ID.
	 *
	 * @return array|object|void|null
	 */
	public static function select_from_refund_log_by_ipn_and_refund_id( $ipn, $refund_id ) {
		global $wpdb;

		return $wpdb->get_row(
			$wpdb->prepare(
				'SELECT id, order_id, refund_id, action_type FROM ' . $wpdb->prefix . 'splitit_async_refund_log WHERE ipn = %s AND refund_id = %s  LIMIT 1',
				array(
					$ipn,
					$refund_id,
				)
			),
			OBJECT
		);
	}

	/**
	 * Get record from transaction log
	 *
	 * @return array|object|void|null
	 */
	public static function select_from_refund_log_orders_without_refund_result() {
		global $wpdb;

		return $wpdb->get_results(
			$wpdb->prepare(
				'SELECT * FROM ' . $wpdb->prefix . 'splitit_async_refund_log WHERE action_type != %s',
				array(
					'done',
				)
			),
			OBJECT
		);
	}

	/**
	 * Get record from transaction log by ipn
	 *
	 * @param int $order_id Order ID.
	 *
	 * @return array|object|void|null
	 */
	public static function select_from_refund_log_by_order_id( $order_id ) {
		global $wpdb;

		return $wpdb->get_row(
			$wpdb->prepare(
				'SELECT id FROM ' . $wpdb->prefix . 'splitit_async_refund_log WHERE order_id = %s LIMIT 1',
				array(
					$order_id,
				)
			),
			OBJECT
		);
	}

	/**
	 * Get info about transaction by order ID
	 *
	 * @param int $order_id Order ID.
	 *
	 * @return false|mixed
	 */
	public static function get_splitit_info_by_order_id( $order_id ) {
		global $wpdb;

		$splitit_transaction_info = $wpdb->get_results(
			$wpdb->prepare(
				'SELECT installment_plan_number, number_of_installments, plan_create_succeed FROM ' . $wpdb->prefix . 'splitit_transactions_log WHERE order_id=%d LIMIT 1',
				array(
					$order_id,
				)
			)
		);

		return $splitit_transaction_info[0] ?? false;
	}

	/**
	 *  Add data about order
	 *
	 * @param array $data Data.
	 */
	public static function add_order_data( $data ) {
		global $wpdb;
		$table_name = $wpdb->prefix . self::$db_order_data;

		$exist = $wpdb->get_row(
			$wpdb->prepare(
				'SELECT id FROM ' . $wpdb->prefix . 'splitit_order_data_with_ipn WHERE ipn = %s ORDER BY ipn DESC LIMIT 0,1',
				array(
					$data['ipn'],
				)
			)
		);

		if ( ! isset( $exist ) ) {
			$wpdb->insert(
				$table_name,
				array(
					'ipn'                          => $data['ipn'],
					'user_id'                      => $data['user_id'],
					'cart_items'                   => $data['cart_items'],
					'shipping_method_cost'         => $data['shipping_method_cost'],
					'shipping_method_title'        => $data['shipping_method_title'],
					'shipping_method_id'           => $data['shipping_method_id'],
					'coupon_amount'                => $data['coupon_amount'],
					'coupon_code'                  => $data['coupon_code'],
					'tax_amount'                   => $data['tax_amount'],
					'user_data'                    => wp_json_encode( $data['user_data'] ),
					'set_shipping_total'           => $data['set_shipping_total'],
					'set_discount_total'           => $data['set_discount_total'],
					'set_discount_tax'             => $data['set_discount_tax'],
					'set_cart_tax'                 => $data['set_cart_tax'],
					'set_shipping_tax'             => $data['set_shipping_tax'],
					'set_total'                    => $data['set_total'],
					'wc_cart'                      => $data['wc_cart'],
					'get_packages'                 => $data['get_packages'],
					'chosen_shipping_methods_data' => $data['chosen_shipping_methods_data'],
					'updated_at'                   => gmdate( 'Y-m-d H:i:s' ),
					'session_id'                   => WC()->session->get_customer_unique_id(),
				)
			);
		} else {
			$wpdb->update(
				$table_name,
				array(
					'ipn'                          => $data['ipn'],
					'user_id'                      => $data['user_id'],
					'cart_items'                   => $data['cart_items'],
					'shipping_method_cost'         => $data['shipping_method_cost'],
					'shipping_method_title'        => $data['shipping_method_title'],
					'shipping_method_id'           => $data['shipping_method_id'],
					'coupon_amount'                => $data['coupon_amount'],
					'coupon_code'                  => $data['coupon_code'],
					'tax_amount'                   => $data['tax_amount'],
					'user_data'                    => wp_json_encode( $data['user_data'] ),
					'set_shipping_total'           => $data['set_shipping_total'],
					'set_discount_total'           => $data['set_discount_total'],
					'set_discount_tax'             => $data['set_discount_tax'],
					'set_cart_tax'                 => $data['set_cart_tax'],
					'set_shipping_tax'             => $data['set_shipping_tax'],
					'set_total'                    => $data['set_total'],
					'wc_cart'                      => $data['wc_cart'],
					'get_packages'                 => $data['get_packages'],
					'chosen_shipping_methods_data' => $data['chosen_shipping_methods_data'],
					'updated_at'                   => gmdate( 'Y-m-d H:i:s' ),
					'session_id'                   => WC()->session->get_customer_unique_id(),
				),
				array( 'ipn' => $data['ipn'] )
			);
		}
	}

	/**
	 * Get information about order by ipn
	 *
	 * @param int $ipn Installment plan number.
	 *
	 * @return false|mixed
	 */
	public static function get_order_info_by_ipn( $ipn ) {
		global $wpdb;

		$order_info = $wpdb->get_results( $wpdb->prepare( 'SELECT * FROM ' . $wpdb->prefix . 'splitit_order_data_with_ipn WHERE ipn=%s LIMIT 1', array( $ipn ) ) );

		return $order_info[0] ?? false;
	}

	/**
	 * Check if order exists by ipn
	 *
	 * @param int $ipn Installment plan number.
	 *
	 * @return bool
	 */
	public static function check_exist_order_by_ipn( $ipn ) {
		global $wpdb;

		$order_id = $wpdb->get_results(
			$wpdb->prepare(
				'SELECT order_id FROM ' . $wpdb->prefix . 'splitit_transactions_log WHERE installment_plan_number=%s LIMIT 1',
				array(
					$ipn,
				)
			)
		);

		return ! empty( $order_id[0]->order_id );
	}

	/**
	 * Check if order exists by ipn
	 *
	 * @param string $ipn Installment plan number.
	 * @param string $refund_id Refund ID.
	 *
	 * @return bool
	 */
	public static function check_exist_order_by_ipn_and_refund_id( $ipn, $refund_id ) {
		global $wpdb;

		$order_id = $wpdb->get_results(
			$wpdb->prepare(
				'SELECT order_id FROM ' . $wpdb->prefix . 'splitit_async_refund_log WHERE ipn=%s AND refund_id=%s LIMIT 1',
				array(
					$ipn,
					$refund_id,
				)
			)
		);

		return ! empty( $order_id[0]->order_id );
	}

	/**
	 * Check if order exists by ipn
	 *
	 * @param int $ipn Installment plan number.
	 *
	 * @return mixed|null
	 */
	public static function get_order_id_by_ipn( $ipn ) {
		global $wpdb;

		$order_id = $wpdb->get_results(
			$wpdb->prepare(
				'SELECT order_id FROM ' . $wpdb->prefix . 'splitit_transactions_log WHERE installment_plan_number=%s LIMIT 1',
				array(
					$ipn,
				)
			)
		);

		return $order_id[0] ?? null;
	}
}
