<?php
/**
 * Remote licensing API helpers ( WooCommerce-style software licence deactivate ).
 *
 * Used by uninstall, settings AJAX, and Divi 4 licence forms. Does not expose keys in output.
 *
 * Hooks:
 * - `dsm_license_remote_deactivate_request_uri` — filters the full deactivate GET URL (returns string).
 * - `dsm_license_remote_deactivate_http_args` — merges into `wp_remote_get` defaults (timeout, sslverify).
 *
 * @package dsm-supreme-modules-pro-for-divi
 */

declare( strict_types=1 );

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

/**
 * Ensure licensing constants exist (mirrors DiviSupreme\Core\License defaults).
 *
 * @return void
 */
function dsm_license_remote_bootstrap_constants(): void {
	if ( ! defined( 'DSM_PRO_APP_API_URL' ) ) {
		define( 'DSM_PRO_APP_API_URL', 'https://divisupreme.com/index.php' );
	}

	if ( ! defined( 'DSM_PRODUCT_ID' ) ) {
		define( 'DSM_PRODUCT_ID', 'DSM-PRO' );
	}

	if ( ! defined( 'DSM_PRO_INSTANCE' ) ) {
		define(
			'DSM_PRO_INSTANCE',
			str_replace( array( 'https://', 'http://' ), '', trim( (string) network_site_url(), '/' ) )
		);
	}
}

/**
 * Whether this site is treated as local for licensing remote calls (skip API deactivate).
 *
 * @return bool
 */
function dsm_license_remote_is_local_instance(): bool {
	dsm_license_remote_bootstrap_constants();

	$instance = trailingslashit( DSM_PRO_INSTANCE );

	return false !== strpos( $instance, base64_decode( 'bG9jYWxob3N0Lw==' ) )
		|| false !== strpos( $instance, base64_decode( 'MTI3LjAuMC4xLw==' ) )
		|| false !== strpos( $instance, base64_decode( 'c3RhZ2luZy53cGVuZ2luZS5jb20=' ) );
}

/**
 * Outcome codes for {@see dsm_license_remote_deactivate_license_key()}.
 *
 * @return non-empty-array<string,string>
 */
function dsm_license_remote_deactivate_outcomes(): array {
	return array(
		'skipped_empty_key'  => 'skipped_empty_key',
		'skipped_local_host' => 'skipped_local_host',
		'deactivated_ok'     => 'deactivated_ok',
		'force_clear_ok'     => 'force_clear_ok',
		'rejected'           => 'rejected',
		'http_error'         => 'http_error',
		'invalid_json'       => 'invalid_json',
		'invalid_block'      => 'invalid_block',
	);
}

/**
 * Call divisupreme licensing API to deactivate a licence key (same contract as dashboard deactivate).
 *
 * Does not mutate local storage; callers clear `dsm_pro_license` when outcomes require it.
 *
 * @param string               $license_key Licence key from storage (sanitize before persist).
 * @param array<string, mixed> $http_overrides Merge into `wp_remote_get` args (`timeout`, etc.).
 * @return array<string, mixed> Keys: outcome (non-empty-string), response_block (?object|null), wp_error (?\WP_Error).
 */
function dsm_license_remote_deactivate_license_key( string $license_key, array $http_overrides = array() ): array {
	dsm_license_remote_bootstrap_constants();

	$key = sanitize_text_field( trim( $license_key ) );

	if ( '' === $key ) {
		return array(
			'outcome'         => dsm_license_remote_deactivate_outcomes()['skipped_empty_key'],
			'response_block'  => null,
			'wp_error'       => null,
		);
	}

	if ( dsm_license_remote_is_local_instance() ) {
		return array(
			'outcome'         => dsm_license_remote_deactivate_outcomes()['skipped_local_host'],
			'response_block'  => null,
			'wp_error'        => null,
		);
	}

	$query = array(
		'woo_sl_action'       => 'deactivate',
		'licence_key'        => $key,
		'product_unique_id'  => DSM_PRODUCT_ID,
		'domain'             => DSM_PRO_INSTANCE,
	);

	$request_uri = DSM_PRO_APP_API_URL . '?' . http_build_query( $query, '', '&' );

	$filtered_uri = apply_filters( 'dsm_license_remote_deactivate_request_uri', $request_uri );

	if ( ! is_string( $filtered_uri ) || '' === $filtered_uri ) {
		$filtered_uri = $request_uri;
	}

	/** This filter is documented in dsm-license-remote.php file header. */
	$http_args = array_merge(
		array(
			'timeout'     => 20,
			'redirection' => 2,
			'sslverify'   => true,
		),
		(array) apply_filters(
			'dsm_license_remote_deactivate_http_args',
			array()
		),
		$http_overrides
	);

	$response = wp_remote_get( $filtered_uri, $http_args );

	if ( is_wp_error( $response ) ) {
		return array(
			'outcome'         => dsm_license_remote_deactivate_outcomes()['http_error'],
			'response_block'  => null,
			'wp_error'        => $response,
		);
	}

	$status = wp_remote_retrieve_response_code( $response );

	if ( 200 !== (int) $status ) {
		return array(
			'outcome'         => dsm_license_remote_deactivate_outcomes()['http_error'],
			'response_block'  => null,
			// phpcs:ignore WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound -- associative array keyed by semantic string.
			'wp_error'       => new \WP_Error( 'dsm_license_http_status', __( 'Unexpected HTTP status from licence server.', 'dsm-supreme-modules-pro-for-divi' ) ),
		);
	}

	$body    = wp_remote_retrieve_body( $response );
	$decoded = json_decode( (string) $body );

	if ( ! is_array( $decoded ) || array() === $decoded ) {
		return array(
			'outcome'        => dsm_license_remote_deactivate_outcomes()['invalid_json'],
			'response_block' => null,
			'wp_error'       => null,
		);
	}

	/** @var object $response_block */
	$response_block = $decoded[ count( $decoded ) - 1 ];

	if ( ! isset( $response_block->status ) ) {
		return array(
			'outcome'         => dsm_license_remote_deactivate_outcomes()['invalid_block'],
			'response_block' => $response_block,
			'wp_error'        => null,
		);
	}

	$force_clear_codes = array( 'e002', 'e104', 'e211', 'e110' );
	$ok_deactivate_codes = array( 's201' );

	$status_ok = isset( $response_block->status_code ) && in_array(
		(string) $response_block->status_code,
		$ok_deactivate_codes,
		true
	);

	$force_clear = isset( $response_block->status_code ) && in_array(
		(string) $response_block->status_code,
		$force_clear_codes,
		true
	);

	if ( 'success' === $response_block->status && $status_ok ) {
		return array(
			'outcome'        => dsm_license_remote_deactivate_outcomes()['deactivated_ok'],
			'response_block' => $response_block,
			'wp_error'       => null,
		);
	}

	if ( 'success' === $response_block->status && ! $status_ok && $force_clear ) {
		return array(
			'outcome'        => dsm_license_remote_deactivate_outcomes()['force_clear_ok'],
			'response_block' => $response_block,
			'wp_error'       => null,
		);
	}

	return array(
		'outcome'        => dsm_license_remote_deactivate_outcomes()['rejected'],
		'response_block' => $response_block,
		'wp_error'       => null,
	);
}

/**
 * Clear stored DSM Pro licence data after successful remote deactivate (or forced clear codes).
 *
 * @return void
 */
function dsm_license_remote_erase_stored_license(): void {
	update_site_option(
		'dsm_pro_license',
		array(
			'key'            => '',
			'last_check'     => time(),
			'expiry_date'    => '',
			'license_status' => '',
		)
	);
}
