<?php

namespace Prodigy\Includes\Api\V1;

use Prodigy\Includes\Frontend\Mappers\Prodigy_Related_Products_Data_Mapper;
use Prodigy\Includes\Helpers\Prodigy_Logger;
use Prodigy\Includes\Models\Prodigy_Products;
use Prodigy\Includes\Prodigy;
use WP_Error;
use WP_Post;
use WP_REST_Request;
use WP_REST_Response;

defined( 'ABSPATH' ) || exit;

/**
 * Class Prodigy_Api_Product
 */
class Prodigy_Api_Product extends Prodigy_Api_Main {

	/** @var object Prodigy_Products */
	private $model;


	/**
	 * CloudPlatform constructor.
	 */
	public function __construct() {
		parent::__construct();
		$this->model = new Prodigy_Products();
		add_action( 'rest_api_init', array( $this, 'register_route_product' ) );
	}

	/**
	 * Register routes.
	 */
	public function register_route_product(): void {
		register_rest_route(
			get_prodigy_plugin_directory_name() . '/v1',
			self::API_PRODUCTS_PATH,
			array(
				'methods'             => 'POST',
				'callback'            => array( $this, 'createOrUpdate' ),
				'permission_callback' => function ( WP_REST_Request $request ) {
					return $this->is_authorization( $request->get_header( 'x-Authorization' ) );
				},
				'args'                => array(
					'id'         => array(
						'default'     => null,
						'type'        => 'integer',
						'required'    => true,
						'description' => 'product with selected id already present',
					),
					'name'       => array(
						'default'  => null,
						'required' => true,
						'type'     => 'string',
					),
					'slug'       => array(
						'default'  => null,
						'required' => true,
						'type'     => 'string',
					),
					'categories' => array(
						'default'           => null,
						'required'          => false,
						'validate_callback' => array( $this, 'validate_callback_categories' ),
					),
					'tags'       => array(
						'default'           => null,
						'required'          => false,
						'validate_callback' => array( $this, 'validate_callback_tags' ),
					),
				),
			)
		);

		register_rest_route(
			get_prodigy_plugin_directory_name() . '/v1',
			self::API_PRODUCTS_PATH . '/' . '(?P<id>\d+)',
			array(
				'methods'             => 'DELETE',
				'callback'            => array( $this, 'delete' ),
				'permission_callback' => function ( WP_REST_Request $request ) {
					return $this->is_authorization( $request->get_header( 'x-Authorization' ) );
				},
				'args'                => array(
					'id' => array(
						'default'           => null,
						'type'              => 'integer',
						'required'          => true,
						'validate_callback' => function ( $param, $request, $key ) {
							return (bool) $this->exists_relationship_product_id( (int) $request->get_url_params()['id'] );
						},
					),
				),
			)
		);

		register_rest_route(
			get_prodigy_plugin_directory_name() . '/v1',
			self::API_PRODUCTS_PATH . '/bulk',
			array(
				'methods'             => 'POST',
				'callback'            => array( $this, 'products_bulk_hiding' ),
				'permission_callback' => function ( WP_REST_Request $request ) {
					return $this->is_authorization( $request->get_header( 'x-Authorization' ) );
				},
				'args'                => array(
					'products' => array(
						'validate_callback' => array( $this->model, 'validate_products_params' ),
					),
				),
			)
		);
	}

	/**
	 * @param WP_REST_Request $request
	 *
	 * @return WP_REST_Response
	 */
	public function products_bulk_hiding( WP_REST_Request $request ): WP_REST_Response {
		$products = $request['products'];

		foreach ( $products as $product ) {
			if ( PRODIGY_DEBUG_MODE ) {
				Prodigy_Logger::add_record( Prodigy_Logger::TYPE_INFO, 'Product hidden ' . $product['id'] );
			}

			if ( isset( $product['id'] ) ) {
				$this->cache->reset_product( (string) $product['id'] );
				$this->cache->reset_catalog();
			}
		}

		return new WP_REST_Response( array(), 204 );
	}

	/**
	 * @param array $categories
	 *
	 * @return bool
	 */
	public function validate_callback_categories( array $categories ): bool {
		return $this->extracted( $categories );
	}

	/**
	 * @param array $tags
	 *
	 * @return bool
	 */
	public function validate_callback_tags( array $tags ): bool {

		return $this->extracted( $tags );
	}

	/**
	 * @param string $slug
	 *
	 * @return bool|WP_Post
	 */
	public function get_product( string $slug ) {
		$args = array(
			'name'        => $slug,
			'post_type'   => Prodigy::get_prodigy_product_type(),
			'numberposts' => 1,
		);

		$posts = get_posts( $args );

		if ( ! empty( $posts ) ) {
			return $posts[0];
		}

		return false;
	}

	/**
	 *
	 * @param WP_REST_Request $request_params
	 *
	 * @return WP_Error|WP_REST_Response
	 */
	public function createOrUpdate( WP_REST_Request $request_params ) {
		global $wpdb;

		$wpdb->query( 'START TRANSACTION' );
		$post_id = $this->model->add_product( $request_params->get_params() );
		if ( is_wp_error( $post_id ) ) {
			$wpdb->query( 'ROLLBACK' );

			return new WP_Error( $post_id->get_error_message(), array( 'status' => $post_id->get_error_data()['status'] ) );
		}

		if ( isset( $post_id ) ) {
			$id_remote_product = get_post_meta( $post_id, Prodigy::PRODIGY_REMOTE_PRODUCT_ID, true );
			$wpdb->query( 'COMMIT' );
			$response['data']['success'] = true;
			$response['data']['id']      = $id_remote_product;

			if ( isset( $id_remote_product ) ) {
				$this->cache->reset_product( (string) $id_remote_product );
				$this->cache->reset_product_brands_list( $id_remote_product );
				$this->cache->reset_catalog();
			}

			return new WP_REST_Response( $response );
		}

		return new WP_Error( 'create_product_error', 'Product sync error.', array( 'status' => \WP_Http::UNPROCESSABLE_ENTITY ) );
	}

	/**
	 * @param WP_REST_Request $request_params
	 *
	 * @return WP_Error|WP_REST_Response
	 */
	public function delete( WP_REST_Request $request_params ) {
		$remote_id      = $request_params->get_url_params()['id'];
		$post_meta_info = $this->exists_relationship_product_id( (int) $remote_id );

		$result      = wp_delete_post( $post_meta_info->post_id, true );
		$result_meta = delete_post_meta( $post_meta_info->post_id, Prodigy::PRODIGY_REMOTE_PRODUCT_ID );
		$this->cache->reset_product( (string) $remote_id );
		$this->cache->reset_catalog();

		$related_products_key = md5(
			wp_json_encode(
				array(
					(string) $remote_id,
					Prodigy_Related_Products_Data_Mapper::UP_SELL,
				)
			)
		);
		$this->cache->reset_related_products( $related_products_key );

		if ( empty( $result ) && ! empty( $result_meta ) ) {
			return new WP_Error( 'delete_product_error', 'Error removing product from database', array( 'status' => 422 ) );
		}

		return new WP_REST_Response( array(), \WP_Http::NO_CONTENT );
	}

	/**
	 * @param array $categories
	 *
	 * @return bool
	 */
	public function extracted( array $categories ): bool {
		$result = true;

		if ( empty( $categories ) ) {
			return true;
		}

		foreach ( $categories as $category ) {

			if ( ! isset( $category['slug'] ) && empty( $category['slug'] ) ) {
				$result = false;
				break;
			}

			if ( ! isset( $category['name'] ) && empty( $category['name'] ) ) {
				$result = false;
				break;
			}

			if ( ( ! isset( $category['id'] ) && empty( $category['id'] ) ) || ! is_int( $category['id'] ) ) {
				$result = false;
				break;
			}
		}

		return $result;
	}
}
