<?php

namespace SugarCalendarBookings\Support\License;

use SugarCalendarBookings\Support\Helpers\Helpers;
use WP_Error;

/**
 * License API Service.
 *
 * Handles communication with the remote license API.
 * Shared between Lite and Pro versions.
 *
 * @since 1.2.0
 */
class LicenseApiService {

	/**
	 * Remote URL for license API.
	 *
	 * @since 1.2.0
	 *
	 * @var string
	 */
	const REMOTE_URL = 'https://bookings.sugarcalendarapi.com/license/v1';

	/**
	 * Verify a license key with the remote API.
	 *
	 * @since 1.2.0
	 *
	 * @param string $license_key License key to verify.
	 *
	 * @return array|WP_Error Array with 'type' and 'success' message on success, WP_Error on failure.
	 */
	public function verify_key( $license_key ) {

		$verify = $this->perform_remote_request( 'verify-key', [ 'tgm-updater-key' => $license_key ] );

		// If it returns false, return generic error.
		if ( ! $verify ) {
			return new WP_Error(
				'api_error',
				__( 'There was an error connecting to the remote key API. Please try again later.', 'sugar-calendar-bookings-scheduling-appointments-lite' )
			);
		}

		// If an error is returned, return WP_Error.
		if ( ! empty( $verify->error ) ) {
			return new WP_Error( 'license_error', $verify->error );
		}

		$success      = isset( $verify->success ) ? $verify->success : __( 'Congratulations! This site is now receiving automatic updates.', 'sugar-calendar-bookings-scheduling-appointments-lite' );
		$license_type = isset( $verify->type ) ? $verify->type : 'pro';

		return [
			'type'    => $license_type,
			'success' => $success,
		];
	}

	/**
	 * Validate a license key with the remote API.
	 *
	 * @since 1.2.0
	 *
	 * @param string $license_key License key to validate.
	 *
	 * @return string|WP_Error License status ('valid', 'expired', 'disabled', 'invalid', 'limit_reached') or WP_Error on API failure.
	 */
	public function validate_key( $license_key ) {

		$validate = $this->perform_remote_request( 'validate-key', [ 'tgm-updater-key' => $license_key ] );

		// If there was a basic API error in validation.
		if ( ! $validate ) {
			return new WP_Error(
				'api_error',
				__( 'There was an error connecting to the remote server. Please try again later.', 'sugar-calendar-bookings-scheduling-appointments-lite' )
			);
		}

		// If a key or author error is returned, the license no longer exists or the user has been deleted.
		if ( isset( $validate->key ) || isset( $validate->author ) ) {
			return 'invalid';
		}

		// If the license has expired.
		if ( isset( $validate->expired ) ) {
			return 'expired';
		}

		// If the license is disabled.
		if ( isset( $validate->disabled ) ) {
			return 'disabled';
		}

		// If the license site activations limit reached.
		if ( isset( $validate->limit_reached ) ) {
			return 'limit_reached';
		}

		// License is valid.
		return 'valid';
	}

	/**
	 * Deactivate a license key with the remote API.
	 *
	 * @since 1.2.0
	 *
	 * @param string $license_key License key to deactivate.
	 *
	 * @return array|WP_Error Array with 'success' message on success, WP_Error on failure.
	 */
	public function deactivate_key( $license_key ) {

		$deactivate = $this->perform_remote_request( 'deactivate-key', [ 'tgm-updater-key' => $license_key ] );

		// If it returns false, return generic error.
		if ( ! $deactivate ) {
			return new WP_Error(
				'api_error',
				__( 'There was an error connecting to the remote server. Please try again later.', 'sugar-calendar-bookings-scheduling-appointments-lite' )
			);
		}

		// If an error is returned, return WP_Error.
		if ( ! empty( $deactivate->error ) ) {
			return new WP_Error( 'license_error', $deactivate->error );
		}

		$success = isset( $deactivate->success ) ? $deactivate->success : __( 'You have deactivated the key from this site successfully.', 'sugar-calendar-bookings-scheduling-appointments-lite' );

		return [
			'success' => $success,
		];
	}

	/**
	 * Send a request to the remote license API.
	 *
	 * @since 1.2.0
	 *
	 * @param string $action The name of the request action.
	 * @param array  $body   The GET query attributes.
	 *
	 * @return object|false Json decoded response on success, false on failure.
	 */
	private function perform_remote_request( $action, $body = [] ) {

		$remote_url = self::REMOTE_URL;

		// Allow override via constant for testing.
		if ( defined( 'SCBOOKINGS_UPDATER_API' ) ) {
			$remote_url = SCBOOKINGS_UPDATER_API;
		}

		// Request query parameters.
		$query_params = wp_parse_args(
			$body,
			[
				'tgm-updater-action'      => $action,
				'tgm-updater-key'         => $body['tgm-updater-key'],
				'tgm-updater-wp-version'  => get_bloginfo( 'version' ),
				'tgm-updater-php-version' => phpversion(),
				'tgm-updater-referer'     => get_option( 'siteurl' ),
			]
		);

		$args = [
			'user-agent' => Helpers::get_default_user_agent(),
			'timeout'    => 30,
		];

		// Perform the query and retrieve the response.
		$response      = wp_remote_get( add_query_arg( $query_params, $remote_url . '/' . $action ), $args );
		$response_code = wp_remote_retrieve_response_code( $response );
		$response_body = wp_remote_retrieve_body( $response );

		// Bail out early if there are any errors.
		if ( $response_code !== 200 || is_wp_error( $response_body ) ) {
			return false;
		}

		// Return the json decoded content.
		return json_decode( $response_body );
	}
}
