<?php
/**
 * Helpful votes REST API controller.
 *
 * @package Ugcify\Admin\API
 */

namespace Ugcify\Admin\API;

use Ugcify\Database\ReviewRepository;
use Ugcify\Review\HelpfulVotes;
use WP_Error;
use WP_REST_Controller;
use WP_REST_Request;
use WP_REST_Response;
use WP_REST_Server;

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

/**
 * Class HelpfulVotesAPI
 */
class HelpfulVotesAPI extends WP_REST_Controller {
	/**
	 * Namespace.
	 *
	 * @var string
	 */
	protected $namespace = 'ugcify/v1';

	/**
	 * Review repository.
	 *
	 * @var ReviewRepository
	 */
	private $repository;

	/**
	 * Helpful votes service.
	 *
	 * @var HelpfulVotes
	 */
	private $helpful_votes;

	/**
	 * Constructor.
	 */
	public function __construct() {
		require_once UGCIFY_PATH . 'includes/Review/HelpfulVotes.php';

		$this->repository    = new ReviewRepository();
		$this->helpful_votes = new HelpfulVotes();
	}

	/**
	 * Register routes.
	 *
	 * @return void
	 */
	public function register_routes() {
		register_rest_route(
			$this->namespace,
			'/reviews/(?P<id>[\d]+)/helpful-vote',
			array(
				array(
					'methods'             => WP_REST_Server::CREATABLE,
					'callback'            => array( $this, 'toggle_vote' ),
					'permission_callback' => array( $this, 'check_vote_permission' ),
					'args'                => array(
						'id'       => array(
							'required'          => true,
							'validate_callback' => function ( $param ) {
								return is_numeric( $param );
							},
						),
						'reaction' => array(
							'required'          => true,
							'sanitize_callback' => 'sanitize_key',
						),
					),
				),
			)
		);
	}

	/**
	 * Check vote permission.
	 *
	 * @return bool|WP_Error
	 */
	public function check_vote_permission() {
		if ( ! is_user_logged_in() ) {
			return new WP_Error(
				'rest_forbidden',
				__( 'You must be logged in to vote on reviews.', 'ugcify' ),
				array( 'status' => 401 )
			);
		}

		return true;
	}

	/**
	 * Toggle a helpful vote.
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return WP_REST_Response|WP_Error
	 */
	public function toggle_vote( $request ) {
		$review_id = absint( $request->get_param( 'id' ) );
		$reaction  = sanitize_key( (string) $request->get_param( 'reaction' ) );

		if ( ! in_array( $reaction, array( 'helpful', 'not_helpful' ), true ) ) {
			return new WP_Error(
				'invalid_reaction',
				__( 'Invalid reaction.', 'ugcify' ),
				array( 'status' => 400 )
			);
		}

		if ( ! $this->repository->find( $review_id ) ) {
			return new WP_Error(
				'review_not_found',
				__( 'Review not found.', 'ugcify' ),
				array( 'status' => 404 )
			);
		}

		$summary              = $this->helpful_votes->toggle_vote( $review_id, get_current_user_id(), $reaction );
		$summary['review_id'] = $review_id;

		return rest_ensure_response(
			array(
				'success' => true,
				'data'    => $summary,
			)
		);
	}
}
