<?php

namespace Saswp;

class Api
{
	static $prefix = 'saswp';
	public string $contentType = "application/x-www-form-urlencoded";
	public string $apiMethod = "GET";
	public string $apiToken = "";
	public string $apiUrl = "";
	public string $apiBearer = "";
	public string $apiUrlPath = "";
	public array $result = [];
	public array $_requestData = [];

	public function getResult(): array
	{
		return $this->result;
	}

	public function setApiBearer($apiBearer): self
	{
		$this->apiBearer = $apiBearer;
		return $this;
	}

	public function setApiMethod($apiMethod): self
	{
		$this->apiMethod = $apiMethod;
		return $this;
	}

	public function setApiToken($apiToken): self
	{
		$this->apiToken = $apiToken;
		return $this;
	}

	public function setApiUrl($apiUrl): self
	{
		$this->apiUrl = $apiUrl;
		return $this;
	}

	public function setApiUrlPath($apiUrlPath): self
	{
		$this->apiUrlPath = $apiUrlPath;
		return $this;
	}

	public function setContentType($contentType): self
	{
		$this->contentType = $contentType;
		return $this;
	}

	public function useJsonContentType(): self
	{
		$this->contentType = "application/json";
		return $this;
	}

	public function setRequestData($_requestData): self
	{
		$this->_requestData = $_requestData;
		return $this;
	}

	public function setApiRequest($methods, $path, $callback)
	{
		$methods = array_map('strtoupper', is_array($methods) ? $methods : [$methods]);
		add_action('rest_api_init', function () use ($methods, $path, $callback) {
			register_rest_route(self::$prefix, $path, [
				'methods' => $methods,
				'permission_callback' => '__return_true',
				'callback' => function ($request) use ($callback) {
					return call_user_func($callback, $request);
				},
			]);
		});
	}

	public function doRequest()
	{
		$this->request($this->apiMethod, $this->apiUrlPath);
	}

	public function get($path)
	{
		return self::request('get', $path);
	}

	public function post($path)
	{
		return self::request('post', $path);
	}

	public function put($path)
	{
		return self::request('put', $path);
	}

	public function delete($path)
	{
		return self::request('delete', $path);
	}

	public function withAuthenticationBearer()
	{
		session_start();
		$this->setApiBearer(sanitize_text_field($_SESSION['saswp_vendor_token'] ?? ''));
		return $this;
	}

	static function url($path = null)
	{
		$path = ltrim($path, '/');
		$path = str_replace('_wpnonce', '_wpnonce=' . wp_create_nonce('wp_rest'), $path);
		return site_url(implode('/', ['wp-json', self::$prefix, $path]));
	}

	private function request($method, $path): self
	{
		$url = $this->apiUrl . $path;
		try {
			if ($method == "DELETE" || $method == "PUT") {
				$this->_requestData['_method'] = $method;
			}
			if (!$this->curlExists()) {
				$requestData = http_build_query($this->_requestData);
				// use key 'http' even if you send the request to https://...
				$options = array(
					'http' => array(
						'header' => "Content-type: " . $this->contentType . "\r\n" .
							"SearchAndStayApiToken: " . $this->apiToken . "\r\n",
						'method' => strtoupper($method),
						'content' => $requestData,
					),
				);
				$context = stream_context_create($options);
				$content = file_get_contents($url, false, $context);
				if ($content) {
					$this->result = json_decode($content, true);
				}
				return $this;
				} else {
				// phpcs:disable WordPress.WP.AlternativeFunctions.curl_curl_init,WordPress.WP.AlternativeFunctions.curl_curl_setopt_array,WordPress.WP.AlternativeFunctions.curl_curl_exec,WordPress.WP.AlternativeFunctions.curl_curl_error,WordPress.WP.AlternativeFunctions.curl_curl_close
				$data_string = json_encode($this->_requestData);
				//set the url, number of POST vars, POST data
				$defaults = array(
					CURLOPT_RETURNTRANSFER => 1,
				);
				if (!in_array(strtoupper($method), ["GET"])) {
					$defaults[CURLOPT_POST] = 1;
					$defaults[CURLOPT_POSTFIELDS] = $data_string;
				} else {
					$url .= "?" . http_build_query($this->_requestData);
				}
				$defaults[CURLOPT_URL] = $url;
				if (isset($this->_requestData["_method"])) {
					switch ($this->_requestData["_method"]) {
						case "DELETE":
							unset($defaults[CURLOPT_POST]);
							$defaults[CURLOPT_CUSTOMREQUEST] = "DELETE";
						case "PUT":
							unset($defaults[CURLOPT_POST]);
							$defaults[CURLOPT_CUSTOMREQUEST] = "PUT";
							break;
					}
				}
				if ($this->apiToken != "") {
					$defaults[CURLOPT_HTTPHEADER][] =
						"SearchAndStayApiToken: " . $this->apiToken;
				}
				if ($this->apiBearer != "") {
					$defaults[CURLOPT_HTTPHEADER][] =
						"Authorization: Bearer " . $this->apiBearer;
				}
                $_urlData = wp_parse_url($url);
                $defaults[CURLOPT_HTTPHEADER][] =
                    "Host: ". ($_urlData['host'] ?? '') ;
                $defaults[CURLOPT_HTTPHEADER][] =
                    "Accept: application/json" ;
                $defaults[CURLOPT_HTTPHEADER][] =
                    "Content-type: ". $this->contentType ;
                $defaults[CURLOPT_HTTPHEADER][] =
                    "User-Agent: Wordpress Wallace" ;
				//open connection
				$ch = curl_init($url);
				curl_setopt_array($ch, ($defaults));
				//execute post
				if (!$content = curl_exec($ch)) {
					print esc_html(curl_error($ch));
					return $this; /* Handle error */
				}
				$this->result = json_decode($content, true) ?? [];
				curl_close($ch);
				return $this;
			}
		} catch (\Exception $e) {
			return $this;
		}

	}

	function curlExists()
	{
		return function_exists('curl_version');
	}
}
