<?php
/**
 * HTTP client for the AccessLens Engine.
 *
 * Wraps all communication with the external engine API.
 * Never throws exceptions — returns WP_Error on failure.
 *
 * @package AccessLens
 */

declare(strict_types=1);

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

/**
 * AccessLens_Engine_Client
 */
class AccessLens_Engine_Client {

	/** Default engine base URL if option is not set (Cloud Run, region Madrid). */
	private const DEFAULT_BASE_URL = 'https://eaa-audit-engine-26367529082.europe-southwest1.run.app';

	/** Timeout in seconds for scan start. */
	private const TIMEOUT_START = 20;

	/** Timeout in seconds for status poll. */
	private const TIMEOUT_POLL = 20;

	/** Timeout in seconds for report generation (PDF can be slow). */
	private const TIMEOUT_REPORT = 120;

	/**
	 * Get configured engine base URL, stripped of trailing slash.
	 */
	private function base_url(): string {
		$url = get_option( 'accesslens_engine_url', self::DEFAULT_BASE_URL );
		return rtrim( esc_url_raw( (string) $url ), '/' );
	}

	/**
	 * Start a new scan. El nivel free/Pro lo decide el motor a partir de la licencia.
	 *
	 * @param string $url         URL to scan.
	 * @param string $mode        "single", "sitemap" or "crawl".
	 * @param string $license_key Clave de licencia Freemius (o '' si free).
	 * @return array{jobId:string,status:string,pageLimit:int}|WP_Error
	 */
	public function start_scan( string $url, string $mode, string $license_key = '' ): array|WP_Error {
		$endpoint = $this->base_url() . '/scan';

		$body = wp_json_encode(
			array(
				'url'        => $url,
				'mode'       => $mode,
				'licenseKey' => $license_key,
			)
		);

		if ( false === $body ) {
			return new WP_Error( 'json_encode', __( 'Error al codificar la solicitud JSON.', 'accesslens' ) );
		}

		$response = wp_remote_post(
			$endpoint,
			array(
				'timeout'     => self::TIMEOUT_START,
				'headers'     => array( 'Content-Type' => 'application/json' ),
				'body'        => $body,
				'data_format' => 'body',
			)
		);

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

		$code = wp_remote_retrieve_response_code( $response );
		if ( 202 !== (int) $code ) {
			return new WP_Error(
				'engine_error',
				sprintf(
					/* translators: %d: HTTP status code */
					__( 'El motor devolvio HTTP %d al iniciar el escaneo.', 'accesslens' ),
					$code
				)
			);
		}

		$data = json_decode( wp_remote_retrieve_body( $response ), true );
		if ( ! is_array( $data ) || empty( $data['jobId'] ) ) {
			return new WP_Error( 'invalid_response', __( 'Respuesta invalida del motor (start).', 'accesslens' ) );
		}

		return $data;
	}

	/**
	 * Poll the status of an existing scan job.
	 *
	 * @param string $job_id Job identifier.
	 * @return array|WP_Error Decoded JSON body or WP_Error.
	 */
	public function get_status( string $job_id ): array|WP_Error {
		$endpoint = $this->base_url() . '/scan/' . rawurlencode( $job_id );

		$response = wp_remote_get(
			$endpoint,
			array( 'timeout' => self::TIMEOUT_POLL )
		);

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

		$code = wp_remote_retrieve_response_code( $response );
		if ( 200 !== (int) $code ) {
			return new WP_Error(
				'engine_error',
				sprintf(
					/* translators: %d: HTTP status code */
					__( 'El motor devolvio HTTP %d al consultar el estado.', 'accesslens' ),
					$code
				)
			);
		}

		$data = json_decode( wp_remote_retrieve_body( $response ), true );
		if ( ! is_array( $data ) ) {
			return new WP_Error( 'invalid_response', __( 'Respuesta invalida del motor (poll).', 'accesslens' ) );
		}

		return $data;
	}

	/**
	 * Request the compliance report and return raw binary body + content-type.
	 *
	 * @param string $job_id     Job identifier.
	 * @param array  $report_meta Report metadata (siteName, siteUrl, entityType, etc.).
	 * @param string $format      "pdf" or "html".
	 * @param string $license_key Clave de licencia Freemius (o '' si free).
	 * @return array{body:string,content_type:string}|WP_Error
	 */
	public function get_report( string $job_id, array $report_meta, string $format = 'pdf', string $license_key = '' ): array|WP_Error {
		$endpoint = $this->base_url() . '/scan/' . rawurlencode( $job_id ) . '/report';

		$payload = array_merge(
			$report_meta,
			array(
				'format'     => in_array( $format, array( 'pdf', 'html' ), true ) ? $format : 'pdf',
				'licenseKey' => $license_key,
			)
		);

		$body = wp_json_encode( $payload );
		if ( false === $body ) {
			return new WP_Error( 'json_encode', __( 'Error al codificar los metadatos del informe.', 'accesslens' ) );
		}

		$response = wp_remote_post(
			$endpoint,
			array(
				'timeout'     => self::TIMEOUT_REPORT,
				'headers'     => array( 'Content-Type' => 'application/json' ),
				'body'        => $body,
				'data_format' => 'body',
			)
		);

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

		$code = wp_remote_retrieve_response_code( $response );
		if ( 200 !== (int) $code ) {
			return new WP_Error(
				'engine_error',
				sprintf(
					/* translators: %d: HTTP status code */
					__( 'El motor devolvio HTTP %d al generar el informe.', 'accesslens' ),
					$code
				)
			);
		}

		return array(
			'body'         => wp_remote_retrieve_body( $response ),
			'content_type' => wp_remote_retrieve_header( $response, 'content-type' ),
		);
	}
}
