<?php
/**
 * WooCommerce REST API Class, ie: /wc/v3/ endpoints.
 *
 * @author   Paul Kilmurray <paul@kilbot.com>
 *
 * @see     http://wcpos.com
 * @package WCPOS\WooCommercePOS
 */

namespace WCPOS\WooCommercePOS;

use WCPOS\WooCommercePOS\Services\Settings;
use WP_Query;

/**
 * WC_API class.
 */
class WC_API {
	/**
	 * Indicates if the current request is for WooCommerce products.
	 *
	 * @var bool
	 */
	private $is_woocommerce_rest_api_products_request = false;

	/**
	 * Indicates if the current request is for WooCommerce variations.
	 *
	 * @var bool
	 */
	private $is_woocommerce_rest_api_variations_request = false;

	/**
	 * Constructor.
	 */
	public function __construct() {
		$pos_only_products = woocommerce_pos_get_settings( 'general', 'pos_only_products' );

		if ( $pos_only_products ) {
			add_filter( 'rest_pre_dispatch', array( $this, 'set_woocommerce_rest_api_request_flags' ), 10, 3 );
			add_filter( 'posts_where', array( $this, 'exclude_pos_only_products_from_api_response' ), 10, 2 );
		}
	}

	/**
	 * Set WooCommerce REST API request flags.
	 *
	 * @param mixed            $result  The dispatch result.
	 * @param \WP_REST_Server  $server  The server instance.
	 * @param \WP_REST_Request $request The request object.
	 */
	public function set_woocommerce_rest_api_request_flags( $result, $server, $request ) {
		$route = $request->get_route();

		if ( 0 === strpos( $route, '/wc/v3/products' ) || 0 === strpos( $route, '/wc/v2/products' ) || 0 === strpos( $route, '/wc/v1/products' ) ) {
			$this->is_woocommerce_rest_api_products_request = true;

			if ( false !== strpos( $route, '/variations' ) ) {
				$this->is_woocommerce_rest_api_variations_request = true;
			}
		}

		return $result;
	}

	/**
	 * Hide POS only products from the API response.
	 *
	 * @param string   $where The WHERE clause of the query.
	 * @param WP_Query $query The WP_Query instance (passed by reference).
	 *
	 * @return string
	 */
	public function exclude_pos_only_products_from_api_response( $where, $query ) {
		global $wpdb;
		$settings_instance = Settings::instance();

		// Hide POS only variations from the API response.
		if ( $this->is_woocommerce_rest_api_variations_request ) {
			$settings = $settings_instance->get_pos_only_variations_visibility_settings();

			if ( isset( $settings['ids'] ) && ! empty( $settings['ids'] ) ) {
				$exclude_ids = array_map( 'intval', (array) $settings['ids'] );
				$ids_format  = implode( ',', array_fill( 0, \count( $exclude_ids ), '%d' ) );
				$where      .= $wpdb->prepare( " AND {$wpdb->posts}.ID NOT IN ($ids_format)", $exclude_ids ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- table name and format are safe.
			}
		} elseif ( $this->is_woocommerce_rest_api_products_request ) {
			// Hide POS only products from the API response.
			$settings = $settings_instance->get_pos_only_product_visibility_settings();

			if ( isset( $settings['ids'] ) && ! empty( $settings['ids'] ) ) {
				$exclude_ids = array_map( 'intval', (array) $settings['ids'] );
				$ids_format  = implode( ',', array_fill( 0, \count( $exclude_ids ), '%d' ) );
				$where      .= $wpdb->prepare( " AND {$wpdb->posts}.ID NOT IN ($ids_format)", $exclude_ids ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- table name and format are safe.
			}
		}

		return $where;
	}
}
