<?php

namespace Wb4Wp\Managers;

use Exception;
use Lcobucci\JWT\Configuration;
use Wb4Wp\Helpers\Encryption_Helper;
use Wb4Wp\Helpers\Environment_Helper;
use Wb4Wp\Helpers\Options_Helper;
use Wb4Wp\Helpers\Provider_Helper;
use Wb4Wp\Helpers\Request_Helper;
use WP_Error;
use WP_REST_Response;

/**
 * Class Provision_Manager
 * @package Wb4Wp\Managers
 */
final class Provision_Manager {

	/**
	 * Starts the onboarding process
	 *
	 * @return WP_REST_Response
	 *
	 * @throws Exception
	 */
	public static function handle_start_onboarding_get() {
		try {
			$token = Options_Helper::get( WB4WP_JWT );
			if ( ! empty( $token ) ) {
				$configuration = Configuration::forUnsecuredSigner();
				$jwt           = $configuration->parser()->parse( $token );
				$claims        = $jwt->claims();
				$body          = array(
					'return_url'          => admin_url( 'admin.php?page=wb4wp-editor' ),
					'provider'            => Provider_Helper::get_provider(),
					'plugin_instantiated' => true,
					'site_id'             => $claims->get( 'siteId' ),
					'user_id'             => $claims->get( 'userId' ),
				);
			} else {
				$body = array(
					'return_url'          => admin_url( 'admin.php?page=wb4wp-editor' ),
					'provider'            => Provider_Helper::get_provider(),
					'plugin_instantiated' => true,
				);
			}

			$response = Request_Manager::post(
				Environment_Helper::get_app_gateway_url( 'wb4wp/v1.0/onboarding/model' ),
				array(
					'headers' => array(
						'Content-Type' => 'application/json',
					),
					'body'    => $body,
				)
			);

			if ( ! is_wp_error( $response ) ) {
				$json = json_decode( $response['body'] );

				if ( ! empty( $json->onboarding_url ) ) {
					return new WP_REST_Response(
						array(
							'success'        => true,
							'onboarding_url' => $json->onboarding_url,
						)
					);
				}
			} else {
				Request_Helper::throw_error( wp_json_encode( $response ), __FILE__, __LINE__, 500 );
			}

			return new WP_REST_Response(
				array( 'success' => false )
			);
		} catch ( Exception $ex ) {
			Raygun_Manager::get_instance()->exception_handler( $ex );

			throw $ex;
		}
	}

	/**
	 * Authenticate SSO through our API key
	 *
	 * @return bool|WP_Error|WP_REST_Response
	 *
	 * @throws Exception
	 */
	public static function handle_sso() {
		try {
			$options = Options_Helper::get_all(
				array(
					WB4WP_SITE_ID,
					WB4WP_INSTANCE_API_KEY_KEY,
					WB4WP_CONNECTED_ACCOUNT_ID,
					WB4WP_INSTANCE_UUID_KEY,
					WB4WP_JWT,
					WB4WP_PLUGIN_STATE,
					WB4WP_ONBOARDING_ID,
				)
			);

			$required_options = array(
				WB4WP_SITE_ID,
				WB4WP_INSTANCE_API_KEY_KEY,
				WB4WP_CONNECTED_ACCOUNT_ID,
			);
			foreach ( $required_options as $option ) {
				if ( empty( $options->get( $option ) ) ) {
					return Request_Helper::throw_error(
						array(
							'success' => false,
							'error'   => "$option is empty",
						),
						__FILE__,
						__LINE__,
						500
					);
				}
			}

			$options_to_save = array();

			$instance_uuid = $options->get( WB4WP_INSTANCE_UUID_KEY, uniqid() );
			if ( $instance_uuid !== $options->get( WB4WP_INSTANCE_UUID_KEY ) ) {
				$options_to_save[ WB4WP_INSTANCE_UUID_KEY ] = $instance_uuid;
			}

			$post_body = array(
				'plugin_id'         => $instance_uuid,
				'instance_url'      => get_bloginfo( 'wpurl' ),
				'wordpress_version' => get_bloginfo( 'version' ),
				'plugin_version'    => env( 'WB4WP_PLUGIN_VERSION' ),
				'token'             => $options->get( WB4WP_JWT ),
				// The JWT can be optional, no empty check required.
			);

			$response = Request_Manager::post(
				Environment_Helper::get_app_gateway_url( 'wordpress/v1.0/builder/sso' ),
				array(
					'headers' => array(
						'Content-Type' => 'application/json',
						'X-API-KEY'    => Encryption_Helper::decrypt( $options->get( WB4WP_INSTANCE_API_KEY_KEY ) ),
						'X-ACCOUNT-ID' => $options->get( WB4WP_CONNECTED_ACCOUNT_ID ),
					),
					'body'    => $post_body,
				)
			);

			if ( ! is_wp_error( $response ) ) {
				$json = json_decode( $response['body'] );

				if ( ! empty( $json->authentication ) ) {
					// Store the sso jwt token and ttl in the settings.
					$options_to_save[] = array(
						WB4WP_SSO_JWT_TOKEN,
						Encryption_Helper::encrypt( $json->authentication ),
						true,
					);
					$options_to_save[] = array( WB4WP_SSO_JWT_TTL, strtotime( '+60 minutes', time() ) );

					Options_Helper::set_all( $options_to_save );

					return new WP_REST_Response(
						array(
							'success'           => true,
							'jwt'               => $json->authentication,
							'site_id'           => $options->get( WB4WP_SITE_ID ),
							'plugin_state'      => $options->get( WB4WP_PLUGIN_STATE, 'new' ),
							'has_onboarding_id' => ! empty( $options->get( WB4WP_ONBOARDING_ID ) ),
							'onboarding_id'     => $options->get( WB4WP_ONBOARDING_ID ),
						)
					);
				}
			} else {
				Options_Helper::set_all( $options_to_save );
			}

			// phpcs:ignore
			return Request_Helper::throw_error( wp_json_encode( $response ), __FILE__, __LINE__, 500 );
		} catch ( Exception $ex ) {
			Raygun_Manager::get_instance()->exception_handler( $ex );

			throw $ex;
		}
	}

	/**
	 * Stores a new sso JWT
	 *
	 * (this functionality is used by the WP-API
	 * which does a renewal on the JWT and sends
	 * it back to the plugin)
	 *
	 * @param $request
	 *
	 * @throws Exception
	 */
	public function update_token( $request ) {
		try {
			$json = $request->get_json_params();

			if ( ! empty( $json['token'] ) ) {
				Options_Helper::set( WB4WP_SSO_JWT_TOKEN, $json['token'], true );
			}
		} catch ( Exception $ex ) {
			Raygun_Manager::get_instance()->exception_handler( $ex );

			throw $ex;
		}
	}

	/**
	 * Deletes the onboarding_id from WP_Options
	 *
	 * @throws Exception
	 */
	public function delete_onboarding_id() {
		try {
			if ( ! Options_Helper::remove( WB4WP_ONBOARDING_ID ) ) {
				return new WP_REST_Response( 'Could not delete onboarding ID', 500 );
			}

			return new WP_REST_Response( null, 204 );
		} catch ( Exception $ex ) {
			Raygun_Manager::get_instance()->exception_handler( $ex );

			throw $ex;
		}
	}

}
