<?php
declare(strict_types=1);

// This sub-system intentionally uses PHP namespaces (DMRS\MBS\Api)
// rather than the MBS_ prefix convention used by the rest of the plugin. This is a
// deliberate architectural boundary for the license/API layer.
namespace DMRS\MBS\Api;

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

/**
 * File Path: includes/api/class-mbs-license-client.php
 *
 * License Client Orchestrator
 *
 * Thin parent class that coordinates all license sub-handlers.
 * Public API is backward-compatible with all callers.
 *
 * Phase 3a cleanup (2026-04-19):
 *   · Deleted clear_all()           — PLG-043, zero callers, redundant with
 *     per-class clear() + uninstall.php wildcard wipe
 *   · Deleted schedule_daily_ping() — PLG-043, zero callers, cron is scheduled
 *     directly by bookshowroom.php activation hook
 *   · Deleted log_api_request()     — PLG-042, facade now bypassed in favor
 *     of MBS_License_Request_Log::log_and_return() called directly by each
 *     API sub-class. No external callers of this facade existed.
 *   · Deleted $request_log member + use import — no longer needed.
 *
 * @package MyBookShowroom
 * @subpackage API
 * @since 1.0.0
 */

use DMRS\MBS\Api\License\MBS_License_Credentials;
use DMRS\MBS\Api\License\MBS_License_Registration;
use DMRS\MBS\Api\License\MBS_License_Activation;
use DMRS\MBS\Api\License\MBS_License_Ping;
use WP_Error;

/**
 * Class MBS_License_Client
 *
 * Single public entry point for all license operations.
 */
final class MBS_License_Client {

	private MBS_License_Credentials  $credentials;
	private MBS_License_Registration $registration;
	private MBS_License_Activation   $activation;
	private MBS_License_Ping         $ping;

	public function __construct() {
		$this->credentials  = new MBS_License_Credentials();
		$this->registration = new MBS_License_Registration();
		$this->activation   = new MBS_License_Activation();
		$this->ping         = new MBS_License_Ping();
	}

	/**
	 * Register a free license key using the supplied email.
	 *
	 * @param string $email Email address for free key registration.
	 * @return array|WP_Error
	 */
	public function register( string $email ): array|WP_Error {
		return $this->registration->register( $email );
	}

	/**
	 * Activate a license key on this domain.
	 *
	 * @param string $license_key License key.
	 * @return array|WP_Error
	 */
	public function activate( string $license_key ): array|WP_Error {
		return $this->activation->activate( $license_key );
	}

	/**
	 * Deactivate the current license on this domain.
	 *
	 * @param string $license_key License key (may be empty — reads from stored credentials).
	 * @return array|WP_Error
	 */
	public function deactivate( string $license_key = '' ): array|WP_Error {
		return $this->activation->deactivate( $license_key );
	}

	/**
	 * Validate current license status (daily ping).
	 *
	 * @return array|WP_Error
	 */
	public function validate(): array|WP_Error {
		return $this->ping->validate();
	}

	/**
	 * Check if a valid license is registered.
	 *
	 * @return bool
	 */
	public function is_registered(): bool {
		return $this->credentials->is_registered();
	}

	/**
	 * Get stored license credentials (decrypted) for display.
	 *
	 * @return array|null
	 */
	public function get_credentials(): ?array {
		return $this->credentials->retrieve();
	}

	/**
	 * Get HMAC parameters for API requests.
	 *
	 * @return array
	 */
	public function get_hmac_params(): array {
		$api_secret = \MBS_Encryption::decrypt( get_option( 'mbs_api_secret_encrypted', '' ) ) ?: '';

		// PLG-045: avoid eager wp_generate_uuid4() evaluation — get_option() default
		// argument is always evaluated, so a new uuid4 was generated on every call
		// even when a stored nonce exists. Read first; generate only if absent.
		$nonce = get_option( 'mbs_api_nonce' );
		if ( ! $nonce ) {
			$nonce = wp_generate_uuid4();
		}

		return array(
			'domain'     => wp_parse_url( home_url(), PHP_URL_HOST ) ?: '',
			'timestamp'  => time(),
			'nonce'      => $nonce,
			'api_secret' => $api_secret,
		);
	}
}
