<?php
/**
 * Talks to the hosted detection API. All the heavy lifting (headless browser,
 * screenshots, diffing) lives on the server — this just sends URLs and renders
 * the report that comes back.
 *
 * @package UpdateGuardian
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Thin HTTP client for the Update Guardian service.
 */
class Upguard_Client {

	const OPT_API_URL = 'upguard_api_url';
	const OPT_LICENSE = 'upguard_license_key';

	/**
	 * The default Update Guardian service endpoint. The free tier requires no
	 * account or key, so the plugin works out of the box.
	 */
	const DEFAULT_API_URL = 'https://ug-api.sumeetsarna.com';

	/**
	 * Absolute paths (e.g. "/", "/shop/") the user wants monitored.
	 *
	 * @return string[]
	 */
	public function monitored_paths() {
		$raw = (string) get_option( 'upguard_paths', "/\n" );
		$paths = array_filter( array_map( 'trim', preg_split( '/\r\n|\r|\n/', $raw ) ) );
		return array_values( $paths );
	}

	/**
	 * Capture (or replace) the baseline for this site.
	 *
	 * @return array|WP_Error Decoded response body or an error.
	 */
	public function capture_baseline() {
		return $this->request( '/v1/baseline' );
	}

	/**
	 * Compare the live site against the stored baseline.
	 *
	 * @return array|WP_Error Decoded response body or an error.
	 */
	public function compare() {
		return $this->request( '/v1/compare' );
	}

	/**
	 * POST the site URL + monitored paths to an API endpoint.
	 *
	 * @param string $endpoint API path, e.g. "/v1/compare".
	 * @return array|WP_Error
	 */
	private function request( $endpoint ) {
		$api_url = untrailingslashit( (string) get_option( self::OPT_API_URL, self::DEFAULT_API_URL ) );
		if ( '' === $api_url ) {
			$api_url = self::DEFAULT_API_URL;
		}

		// A license is optional: without one the service applies its free tier.
		$headers = array( 'Content-Type' => 'application/json' );
		$license = upguard_service_token();
		if ( '' !== $license ) {
			$headers['Authorization'] = 'Bearer ' . $license;
			$headers['X-License-Id']  = upguard_license_id();
		}

		$response = wp_remote_post(
			$api_url . $endpoint,
			array(
				'timeout' => 120,
				'headers' => $headers,
				'body'    => wp_json_encode(
					array(
						'siteUrl' => home_url(),
						'paths'   => $this->monitored_paths(),
					)
				),
			)
		);

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

		$code = wp_remote_retrieve_response_code( $response );
		$body = json_decode( wp_remote_retrieve_body( $response ), true );

		if ( $code < 200 || $code >= 300 ) {
			// Sanitize the remote error before it travels through options/notices.
			$message = isset( $body['error'] ) ? sanitize_text_field( (string) $body['error'] ) : sprintf( 'HTTP %d', $code );
			return new WP_Error( 'upguard_api', $message );
		}

		return is_array( $body ) ? $body : array();
	}
}
