<?php
/**
 * Reviews Bulk Actions REST API Controller
 *
 * @package Ugcify\Admin\API
 */

namespace Ugcify\Admin\API;

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

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

	/**
	 * Rest base
	 *
	 * @var string
	 */
	protected $rest_base = 'reviews/bulk';

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

	/**
	 * Review validator
	 *
	 * @var ReviewValidator
	 */
	private $validator;

	/**
	 * Constructor
	 */
	public function __construct() {
		$this->repository = new ReviewRepository();
		$this->validator  = new ReviewValidator();
	}

	/**
	 * Register routes
	 */
	public function register_routes() {
		// Bulk update status.
		register_rest_route(
			$this->namespace,
			'/' . $this->rest_base . '/status',
			array(
				'methods'             => WP_REST_Server::EDITABLE,
				'callback'            => array( $this, 'bulk_update_status' ),
				'permission_callback' => array( $this, 'check_admin_permission' ),
			)
		);

		// Bulk delete.
		register_rest_route(
			$this->namespace,
			'/' . $this->rest_base . '/delete',
			array(
				'methods'             => WP_REST_Server::EDITABLE,
				'callback'            => array( $this, 'bulk_delete' ),
				'permission_callback' => array( $this, 'check_admin_permission' ),
			)
		);
	}

	/**
	 * Require manage_options or manage_woocommerce for admin-only endpoints.
	 *
	 * @return bool|\WP_Error
	 */
	public function check_admin_permission() {
		if ( current_user_can( 'manage_options' ) || current_user_can( 'manage_woocommerce' ) ) {
			return true;
		}
		return new \WP_Error(
			'rest_forbidden',
			__( 'Sorry, you are not allowed to access this resource.', 'ugcify' ),
			array( 'status' => 403 )
		);
	}

	/**
	 * Bulk update review status
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return WP_REST_Response|WP_Error
	 */
	public function bulk_update_status( $request ) {
		$data = $request->get_json_params();

		if ( empty( $data ) ) {
			return new WP_Error(
				'invalid_request',
				__( 'Invalid JSON data.', 'ugcify' ),
				array( 'status' => 400 )
			);
		}

		// Validate required fields.
		if ( empty( $data['ids'] ) || ! is_array( $data['ids'] ) ) {
			return new WP_Error(
				'missing_ids',
				__( 'Review IDs are required and must be an array.', 'ugcify' ),
				array( 'status' => 400 )
			);
		}

		if ( empty( $data['status'] ) ) {
			return new WP_Error(
				'missing_status',
				__( 'Status is required.', 'ugcify' ),
				array( 'status' => 400 )
			);
		}

		// Validate status.
		$validation = $this->validator->validate_status( $data['status'] );
		if ( is_wp_error( $validation ) ) {
			return new WP_Error(
				$validation->get_error_code(),
				$validation->get_error_message(),
				array( 'status' => 400 )
			);
		}

		$ids     = array_map( 'intval', $data['ids'] );
		$status  = $data['status'];
		$updated = array();
		$failed  = array();

		foreach ( $ids as $id ) {
			// Check if review exists.
			$review = $this->repository->find( $id );
			if ( ! $review ) {
				$failed[] = array(
					'id'    => $id,
					'error' => __( 'Review not found.', 'ugcify' ),
				);
				continue;
			}

			if ( 'approved' === $status && (int) $review->product_id <= 0 ) {
				$failed[] = array(
					'id'    => $id,
					'error' => __( 'A product must be assigned before publishing this review.', 'ugcify' ),
				);
				continue;
			}

			$old_status = $review->status;

			// Update status.
			$result = $this->repository->update( $id, array( 'status' => $status ) );

			if ( is_wp_error( $result ) ) {
				$failed[] = array(
					'id'    => $id,
					'error' => $result->get_error_message(),
				);
			} else {
				$updated[] = $id;

				// Fire status changed action for email triggers.
				if ( $status !== $old_status ) {
					do_action( 'ugcify_review_status_changed', $id, $status, $old_status );
				}
			}
		}

		return new WP_REST_Response(
			array(
				'success'       => true,
				'updated'       => $updated,
				'updated_count' => count( $updated ),
				'failed'        => $failed,
				'failed_count'  => count( $failed ),
				'status'        => $status,
			),
			200
		);
	}

	/**
	 * Bulk delete reviews
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return WP_REST_Response|WP_Error
	 */
	public function bulk_delete( $request ) {
		$data = $request->get_json_params();

		if ( empty( $data ) ) {
			return new WP_Error(
				'invalid_request',
				__( 'Invalid JSON data.', 'ugcify' ),
				array( 'status' => 400 )
			);
		}

		// Validate required fields.
		if ( empty( $data['ids'] ) || ! is_array( $data['ids'] ) ) {
			return new WP_Error(
				'missing_ids',
				__( 'Review IDs are required and must be an array.', 'ugcify' ),
				array( 'status' => 400 )
			);
		}

		$ids     = array_map( 'intval', $data['ids'] );
		$deleted = array();
		$failed  = array();

		foreach ( $ids as $id ) {
			// Check if review exists.
			$review = $this->repository->find( $id );
			if ( ! $review ) {
				$failed[] = array(
					'id'    => $id,
					'error' => __( 'Review not found.', 'ugcify' ),
				);
				continue;
			}

			// Delete review.
			$result = $this->repository->delete( $id );

			if ( is_wp_error( $result ) ) {
				$failed[] = array(
					'id'    => $id,
					'error' => $result->get_error_message(),
				);
			} else {
				$deleted[] = $id;
			}
		}

		return new WP_REST_Response(
			array(
				'success'        => true,
				'deleted'        => $deleted,
				'deleted_count'  => count( $deleted ),
				'failed'         => $failed,
				'failed_count'   => count( $failed ),
			),
			200
		);
	}
}
