<?php
/**
 * Payment retry repository.
 *
 * @since 2.6.10
 *
 * @package Masteriyo\Repository
 */

namespace Masteriyo\Repository;

defined( 'ABSPATH' ) || exit;


use Masteriyo\Database\Model;
use Masteriyo\Repository\AbstractRepository;

/**
 * Payment retry repository class.
 */
class PaymentRetryRepository extends AbstractRepository implements RepositoryInterface {
	/**
	 * Create a payment retry in the database.
	 *
	 * @since 2.6.10
	 *
	 * @param \Masteriyo\Models\PaymentRetry $payment_retry Payment retry object.
	 */
	public function create( Model &$payment_retry ) {
		global $wpdb;

		if ( ! $payment_retry->get_created_at( 'edit' ) ) {
			$payment_retry->set_created_at( time() );
		}

		$result = $wpdb->insert(
			$payment_retry->get_table_name(),
			/**
			 * Filters new payment retry data before creating.
			 *
			 * @since 2.6.10
			 *
			 * @param array $data Payment retry data.
			 * @param \Masteriyo\Models\PaymentRetry $payment_retry Payment retry object.
			 */
			apply_filters(
				'masteriyo_new_payment_retry_data',
				array(
					'order_id'   => $payment_retry->get_order_id( 'edit' ),
					'status'     => $payment_retry->get_status( 'edit' ),
					'created_at' => gmdate( 'Y-m-d H:i:s', $payment_retry->get_created_at( 'edit' )->getTimestamp() ),
				),
				$payment_retry
			),
			array( '%d', '%s', '%s' )
		);

		if ( $result && $wpdb->insert_id ) {
			$payment_retry->set_id( $wpdb->insert_id );
			$payment_retry->apply_changes();
			$this->clear_cache( $payment_retry );

			/**
			 * Fires after creating a payment retry.
			 *
			 * @since 2.6.10
			 *
			 * @param integer $id The payment retry ID.
			 * @param \Masteriyo\Models\PaymentRetry $object The payment retry object.
			 */
			do_action( 'masteriyo_new_payment_retry', $payment_retry->get_id(), $payment_retry );
		}

	}

	/**
	 * Update a payment retry item in the database.
	 *
	 * @since 2.6.10
	 * @param \Masteriyo\Models\PaymentRetry $payment_retry Payment retry object.
	 */
	public function update( Model &$payment_retry ) {
		global $wpdb;

		$changes = $payment_retry->get_changes();

		$payment_retry_data_keys = array(
			'order_id',
			'status',
			'created_at',
			'modified_at',
		);

		if ( array_intersect( $payment_retry_data_keys, array_keys( $changes ) ) ) {
			$payment_retry->set_modified_at( time() );

			$wpdb->update(
				$payment_retry->get_table_name(),
				array(
					'order_id'    => $payment_retry->get_order_id( 'edit' ),
					'status'      => $payment_retry->get_status( 'edit' ),
					'created_at'  => $payment_retry->get_created_at( 'edit' ) ? gmdate( 'Y-m-d H:i:s', $payment_retry->get_created_at( 'edit' )->getTimestamp() ) : '',
					'modified_at' => $payment_retry->get_modified_at( 'edit' )->getTimestamp(),
				),
				array( 'id' => $payment_retry->get_id() )
			);
		}

		$payment_retry->apply_changes();
		$this->clear_cache( $payment_retry );

		/**
		 * Fires after updating a payment retry.
		 *
		 * @since 2.6.10
		 *
		 * @param integer $id The payment retry ID.
		 * @param \Masteriyo\Models\PaymentRetry $object The payment retry object.
		 */
		do_action( 'masteriyo_update_payment_retry', $payment_retry->get_id(), $payment_retry );
	}

	/**
	 * Remove an payment retry from the database.
	 *
	 * @since 2.6.10
	 * @param \Masteriyo\Models\PaymentRetry $payment_retry payment retry object.
	 * @param array         $args Array of args to pass to the delete method.
	 */
	public function delete( &$payment_retry, $args = array() ) {
		global $wpdb;

		if ( $payment_retry->get_id() ) {
			/**
			 * Fires before deleting a payment retry.
			 *
			 * @since 2.6.10
			 *
			 * @param integer $id The payment retry ID.
			 */
			do_action( 'masteriyo_before_delete_payment_retry', $payment_retry->get_id() );

			$wpdb->delete( $payment_retry->get_table_name(), array( 'id' => $payment_retry->get_id() ) );

			/**
			 * Fires after deleting a payment retry.
			 *
			 * @since 2.6.10
			 *
			 * @param integer $id The payment retry ID.
			 */
			do_action( 'masteriyo_delete_payment_retry', $payment_retry->get_id() );

			$payment_retry->set_id( 0 );

			$this->clear_cache( $payment_retry );
		}
	}

	/**
	 * Read a payment retry from the database.
	 *
	 * @since 2.6.10
	 *
	 * @param \Masteriyo\Models\PaymentRetry $payment_retry payment retry object.
	 *
	 * @throws \Exception If invalid payment retry object object.
	 */
	public function read( &$payment_retry ) {
		global $wpdb;

		$result = $wpdb->get_row(
			$wpdb->prepare(
				"SELECT * FROM {$wpdb->prefix}masteriyo_payment_retries WHERE id = %d;",
				$payment_retry->get_id()
			)
		);

		if ( ! $result ) {
			throw new \Exception( __( 'Invalid user course.', 'learning-management-system' ) );
		}

		$payment_retry->set_props(
			array(
				'order_id'    => $result->order_id,
				'status'      => $result->status,
				'created_at'  => $this->string_to_timestamp( $result->created_at ),
				'modified_at' => $this->string_to_timestamp( $result->modified_at ),
			)
		);

		$payment_retry->set_object_read( true );

		/**
		 * Fires after reading a payment retry from database.
		 *
		 * @since 2.6.10
		 *
		 * @param integer $id The payment retry ID.
		 * @param \Masteriyo\Models\PaymentRetry $object The payment retry object.
		 */
		do_action( 'masteriyo_payment_retry_read', $payment_retry->get_id(), $payment_retry );
	}

	/**
	 * Clear meta cache.
	 *
	 * @since 2.6.10
	 *
	 * @param \Masteriyo\Models\PaymentRetry $payment_retry Payment retry object.
	 */
	public function clear_cache( &$payment_retry ) {
		wp_cache_delete( 'item' . $payment_retry->get_id(), 'masteriyo-payment-retry' );
		wp_cache_delete( 'items-' . $payment_retry->get_id(), 'masteriyo-payment-retry' );
	}

	/**
	 * Fetch payment retry items.
	 *
	 * @since 2.6.10
	 *
	 * @param array $query_vars Query vars.
	 * @return \Masteriyo\Models\PaymentRetry[]
	 */
	public function query( $query_vars, $query ) {
		global $wpdb;

		$search_criteria = array();
		$sql[]           = "SELECT * FROM {$wpdb->prefix}masteriyo_payment_retries";

		if ( ! empty( $query_vars['status'] ) ) {
			$search_criteria[] = $this->create_sql_in_query( 'status', $query_vars['status'] );
		}

		if ( ! empty( $query_vars['order'] ) ) {
			$search_criteria[] = $this->create_sql_in_query( 'order_id', $query_vars['order'] );
		}
		if ( $search_criteria ) {
			$criteria = implode( ' AND ', $search_criteria );
			$sql[]    = 'WHERE ' . $criteria;
		}

		// Construct order and order by part.
		$sql[] = 'ORDER BY ' . sanitize_sql_orderby( $query_vars['orderby'] . ' ' . $query_vars['order'] );

		// Construct limit part.
		$per_page = $query_vars['per_page'];
		$page     = $query_vars['page'];

		if ( $page > 0 && $per_page > 0 ) {
			$count_sql         = $sql;
			$count_sql[0]      = "SELECT COUNT(*) FROM {$wpdb->prefix}masteriyo_payment_retries ";
			$count_sql         = implode( ' ', $count_sql ) . ';';
			$query->found_rows = absint( $wpdb->get_var( $count_sql ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared

			$offset = ( $page - 1 ) * $per_page;
			$sql[]  = $wpdb->prepare( 'LIMIT %d, %d', $offset, $per_page );
		}

		// Generate SQL from the SQL parts.
		$sql = implode( ' ', $sql ) . ';';

		// Fetch the results.
		$payment_retries = $wpdb->get_results( $sql, ARRAY_A ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared

		$query->rows_count = count( $payment_retries );

		return array_map(
			function( $payment_retry ) {
				$object = masteriyo( 'payment-retry' );
				$object->set_props( $payment_retry );

				return $object;
			},
			$payment_retries
		);
	}
}
