<?php
/**
 * MailerLite Integration REST Controller.
 *
 * @since 2.14.4
 *
 * @subpackage Masteriyo\Addons\MailerLiteIntegration
 */

namespace Masteriyo\Addons\MailerLiteIntegration\Controllers;

defined( 'ABSPATH' ) || exit;

use Masteriyo\Addons\MailerLiteIntegration\MailerLiteIntegrationSettings;
use Masteriyo\Helper\Permission;
use Masteriyo\Addons\MailerLiteIntegration\API\API;
use Masteriyo\RestApi\Controllers\Version1\CrudController;

/**
 * MailerLiteIntegrationController class.
 *
 * @since 2.14.4
 */
class MailerLiteIntegrationController extends CrudController {
	/**
	 * Endpoint namespace.
	 *
	 * @since 2.14.4
	 *
	 * @var string
	 */
	protected $namespace = 'masteriyo/pro/v1';

	/**
	 * Route base.
	 *
	 * @since 2.14.4
	 *
	 * @var string
	 */
	protected $rest_base = 'mailerlite-integration';

	/** Object type.
	 *
	 * @since 2.14.4
	 *
	 * @var string
	 */
	protected $object_type = 'mailerlite-integration';

	/**
	 * Permission class.
	 *
	 * @since 2.14.4
	 *
	 * @var \Masteriyo\Helper\Permission;
	 */
	protected $permission = null;

	/**
	 * API client instance.
	 *
	 * @since 2.14.4
	 *
	 * @var \Masteriyo\Addons\MailerLiteIntegration\API\API
	 */
	private $api_client;

	/**
	 * Constructor.
	 *
	 * @since 2.14.4
	 *
	 * @param \Masteriyo\Helper\Permission $permission
	 */
	public function __construct( ?Permission $permission = null ) {
		$this->permission = $permission;
		$this->api_client = new API( MailerLiteIntegrationSettings::get_api_key() );
	}

	/**
	 * Register routes.
	 *
	 * @since 2.14.4
	 *
	 * @return void
	 */
	public function register_routes() {
		register_rest_route(
			$this->namespace,
			'/' . $this->rest_base . '/groups',
			array(
				array(
					'methods'             => \WP_REST_Server::READABLE,
					'callback'            => array( $this, 'get_groups' ),
					'permission_callback' => array( $this, 'get_items_permissions_check' ),
				),
			)
		);

		register_rest_route(
			$this->namespace,
			'/' . $this->rest_base . '/connect',
			array(
				array(
					'methods'             => \WP_REST_Server::CREATABLE,
					'callback'            => array( $this, 'connect' ),
					'permission_callback' => array( $this, 'get_items_permissions_check' ),
				),
			)
		);

		register_rest_route(
			$this->namespace,
			'/' . $this->rest_base . '/disconnect',
			array(
				array(
					'methods'             => \WP_REST_Server::DELETABLE,
					'callback'            => array( $this, 'disconnect' ),
					'permission_callback' => array( $this, 'get_items_permissions_check' ),
				),
			)
		);
	}

	/**
	 * Check if a given request has access to read items.
	 *
	 * @since 2.14.4
	 *
	 * @param  WP_REST_Request $request Full details about the request.
	 *
	 * @return WP_Error|boolean
	 */
	public function get_items_permissions_check( $request ) {
		if ( is_null( $this->permission ) ) {
			return new \WP_Error(
				'masteriyo_null_permission',
				__( 'The permission object is missing. Unable to verify access rights.', 'learning-management-system' ),
				array( 'status' => 403 )
			);
		}

		return current_user_can( 'manage_options' ) || current_user_can( 'manage_masteriyo_settings' );
	}

	/**
	 * Get MailerLite groups from the API.
	 *
	 * This function fetches the MailerLite groups from the API and caches them in the database.
	 *
	 * @since 2.14.4
	 *
	 * @param \WP_REST_Request $request The REST request object.
	 *
	 * @return \WP_REST_Response The response object containing the MailerLite groups.
	 */
	public function get_groups( $request ) {
		$force_fetch = masteriyo_string_to_bool( $request->get_param( 'force' ) );

		if ( $force_fetch ) {
			delete_option( 'masteriyo_mailerlite_groups' );
		}

		$groups = get_option( 'masteriyo_mailerlite_groups', array() );

		if ( empty( $groups ) ) {
			$groups = $this->api_client->get_groups();

			if ( is_wp_error( $groups ) ) {
				return $groups;
			}

			if ( isset( $groups['data'] ) ) {
				$groups = $groups['data'];
				update_option( 'masteriyo_mailerlite_groups', $groups );
			} else {
				return new \WP_Error(
					'masteriyo_invalid_api_response',
					__( 'Failed to retrieve MailerLite lists. Please check the API key or try again later.', 'learning-management-system' ),
					array( 'status' => 500 )
				);
			}
		}

		return rest_ensure_response( $groups );
	}

	/**
	 * Connect to MailerLite with validating the API key.
	 *
	 * This function validates the provided API key and stores it in the settings if valid.
	 *
	 * @since 2.14.4
	 *
	 * @param \WP_REST_Request $request The REST request object.
	 *                                 Required parameter: api_key
	 *
	 * @return \WP_REST_Response The response object containing the success status and message.
	 *                           Error response: masteriyo_invalid_api_key
	 *
	 * @throws \WP_Error If the API key is invalid.
	 */
	public function connect( $request ) {
		$api_key      = sanitize_text_field( $request['api_key'] ?? '' );
		$verify_again = masteriyo_string_to_bool( $request['verify_again'] ?? false );

		if ( $verify_again ) {
			$api_key = MailerLiteIntegrationSettings::get_api_key();
		}

		if ( empty( $api_key ) ) {
			return new \WP_Error(
				'masteriyo_invalid_api_key',
				__( 'API key is required to establish a connection.', 'learning-management-system' ),
				array( 'status' => 400 )
			);
		}

		$is_valid = $this->api_client->validate_api_key( $api_key );

		if ( ! $is_valid ) {
			return new \WP_Error(
				'masteriyo_invalid_api_key',
				__( 'The provided API key is invalid. Please verify the key and try again.', 'learning-management-system' ),
				array( 'status' => 401 )
			);
		}

		MailerLiteIntegrationSettings::set( 'api_key', $api_key );
		MailerLiteIntegrationSettings::set( 'is_connected', true );

		$message = $verify_again
		? __( 'API key re-verified successfully.', 'learning-management-system' )
		: __( 'Connected to MailerLite successfully.', 'learning-management-system' );

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

	/**
	 * Disconnects from MailerLite integration.
	 *
	 * This function clears the API key and sets the is_connected flag to false.
	 *
	 * @since 2.14.4
	 *
	 * @param \WP_REST_Request $request The REST request object.
	 *
	 * @return \WP_REST_Response The response object containing the success status and message.
	 */
	public function disconnect( $request ) {
		MailerLiteIntegrationSettings::set( 'api_key', '' );
		MailerLiteIntegrationSettings::set( 'is_connected', false );
		MailerLiteIntegrationSettings::settings_remove();

		return rest_ensure_response(
			array(
				'success' => true,
				'message' => __( 'Disconnected from MailerLite successfully.', 'learning-management-system' ),
			)
		);
	}
}
