<?php
/**
 * Live licence validation.
 *
 * The licence used to be checked once, when the key was typed into settings,
 * and never again. Nothing noticed the expiry date passing: the gateway kept
 * appearing at checkout, buyers kept sending crypto, and the API kept
 * forwarding the notifications. A licence bought for one month still worked a
 * year later.
 *
 * This asks the API on the requests where the answer matters — rendering the
 * checkout, and rendering the payment page — rather than on a timer. A stale
 * "still valid" is exactly the failure being fixed, so nothing is cached
 * between page loads.
 *
 * Two states:
 *
 *   valid    the API says the licence is active and unexpired.
 *   blocked  no key at all, or the API says the key is expired, inactive or
 *            unknown.
 *
 * No key counts as blocked because this is the PRO plugin and there is no
 * unlicensed tier inside it — the free product is a separate plugin. The panel
 * is fully unlocked either way, so a merchant can configure every coin before
 * activating; what a key buys is the ability to actually take payment. Leaving
 * a keyless install able to reach checkout would be the worst of both, since
 * the API refuses to forward the notification and the customer's crypto is
 * never confirmed.
 *
 * If the API cannot be reached the licence is treated as valid. An outage on
 * the Cryptoniq side must not take down every merchant's checkout at once, and
 * "I could not ask" is not the same answer as "no". This matches the choice
 * already made in admin/validators.php when a key is saved.
 */

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

/**
 * Ask the API about this site's licence.
 *
 * Memoised for the current request only: a single checkout render asks several
 * times over, and that should still be one HTTP call.
 *
 * @return array{state:string, status:string}
 */
function cryptoniq_license_state() {

	static $cached = null;

	if ( null !== $cached ) {
		return $cached;
	}

	$key = cryptoniq_get_option( 'license_key' );

	if ( empty( $key ) ) {
		$cached = array( 'state' => 'blocked', 'status' => 'none' );
		return $cached;
	}

	$response = wp_remote_post(
		CRYPTONIQ_API_URL . 'license/website/check',
		array(
			// Short: this sits in front of a page a customer is waiting on.
			'timeout' => 5,
			'headers' => array( 'Content-Type' => 'application/json' ),
			'body'    => wp_json_encode( array( 'licenseKey' => $key ) ),
		)
	);

	if ( is_wp_error( $response ) || 200 !== (int) wp_remote_retrieve_response_code( $response ) ) {
		// Unreachable, not invalid.
		$cached = array( 'state' => 'valid', 'status' => 'unreachable' );
		return $cached;
	}

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

	if ( ! is_array( $body ) || ! isset( $body['valid'] ) ) {
		$cached = array( 'state' => 'valid', 'status' => 'unreadable' );
		return $cached;
	}

	$cached = array(
		'state'  => $body['valid'] ? 'valid' : 'blocked',
		'status' => isset( $body['status'] ) ? (string) $body['status'] : 'invalid',
	);

	return $cached;
}

/**
 * Whether this site may take a payment right now.
 *
 * True when there is no key, or when the API rejects the one there is.
 */
function cryptoniq_license_is_blocked() {
	$state = cryptoniq_license_state();
	return 'blocked' === $state['state'];
}

/**
 * The message shown wherever a blocked licence stops something happening.
 */
function cryptoniq_license_notice() {
	return esc_html__( 'License is not valid', 'cryptoniq-pro' );
}

/**
 * Say so on the checkout page.
 *
 * The gateway also removes itself, but a payment method that quietly vanishes
 * leaves the shop owner with no idea why. The notice is what turns it into
 * something they can act on.
 */
add_action( 'woocommerce_before_checkout_form', 'cryptoniq_license_checkout_notice', 5 );
function cryptoniq_license_checkout_notice() {

	if ( ! cryptoniq_license_is_blocked() ) {
		return;
	}

	wc_print_notice( cryptoniq_license_notice(), 'error' );
}
