<?php

declare( strict_types=1 );

namespace DocketConnector\Common\Utilities;

use WP_Error;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Abort if this file is called directly.
}

if ( ! class_exists( Http::class ) ) {

	/**
	 * Things related to HTTP, like $_GET, $_PUT, $_REQUEST, and such.
	 */
	class Http {

		/**
		 * Determine if we are in a request of the specified type.
		 *
		 * Note that 'frontend' is true if Ajax.
		 *
		 * @link  https://github.com/woocommerce/woocommerce/blob/4.0.1/includes/class-woocommerce.php#L289-L306 Inspiration.
		 *
		 * @param string $type admin, ajax, cron, rest, or frontend.
		 *
		 * @return bool|void True if is the type passed. False if not. Void if passed an unsupported type.
		 */
		public function current_request_is( string $type ): ?bool {
			switch ( $type ) {
				case 'admin':
					return is_admin();
				case 'ajax':
					return wp_doing_ajax();
				case 'cron':
					return wp_doing_cron();
				case 'rest':
					return $this->is_rest_api_request();
				case 'frontend':
					return (
							! is_admin()
							|| wp_doing_ajax()
						)
						&& ! wp_doing_cron()
						&& ! $this->is_rest_api_request();
			}
		}

		/**
		 * Returns true if the request is a non-legacy REST API request.
		 *
		 * Legacy REST requests should still run some extra code for backwards compatibility.
		 *
		 * @todo  : replace this function once core WP function is available: https://core.trac.wordpress.org/ticket/42061.
		 *
		 * @link  https://github.com/woocommerce/woocommerce/blob/4.0.1/includes/class-woocommerce.php#L269-L287 Similar source.
		 *
		 * @return bool
		 */
		private function is_rest_api_request() {
			if ( empty( $_SERVER['REQUEST_URI'] ) ) {
				return false;
			}

			$rest_prefix = trailingslashit( rest_get_url_prefix() );

			return ( false !== strpos( $_SERVER['REQUEST_URI'], $rest_prefix ) );
		}

		/**
		 * Get a Response's error message, whether from a WP_Error or from the API response for codes not 200-299.
		 *
		 * @see wp_remote_request()
		 * @see WP_Http::request() Expecting an array like this.
		 *
		 * @param array|WP_Error $response The result of an HTTP response from one of the wp_remote_... functions.
		 *
		 * @return string Empty string means the Response was not any type of error.
		 */
		public function get_api_response_error_message( $response ): string {
			$code = (int) wp_remote_retrieve_response_code( $response );

			/**
			 * Empty string if response was successful.
			 *
			 * @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Status Successful responses are 200-299.
			 */
			if (
				199 < $code
				&& 300 > $code
			) {
				return '';
			}

			if ( $response instanceof WP_Error ) {
				return $response->get_error_message();
			}

			return wp_remote_retrieve_response_message( $response );
		}

		/**
		 * Whether the passed string is an HTTP or HTTPS URL.
		 *
		 * @param string $url
		 *
		 * @return bool Whether the passed string is an HTTP or HTTPS URL.
		 */
		public function is_url_http_or_https( string $url ): bool {
			$url = esc_url( $url, [ 'http', 'https' ] );

			return ! empty( $url );
		}

		/**
		 * Whether the passed string is an HTTPS URL.
		 *
		 * @param string $url
		 *
		 * @return bool Whether the passed string is an HTTPS URL.
		 */
		public function is_https_url( string $url ): bool {
			$url = esc_url( $url, [ 'https' ] );

			return ! empty( $url );
		}
	}
}
