<?php

defined( 'ABSPATH' ) || exit;

/**
 * Bust the short-lived HTTP cache when WordPress "Check again" (?force-check=1) is used, or legacy DSM nonce link.
 *
 * @return bool
 */
function dsm_plugin_updater_should_bust_http_cache() {
	// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Core uses plain GET ?force-check=1 on Updates screen.
	if ( isset( $_GET['force-check'] ) && '1' === sanitize_text_field( wp_unslash( (string) $_GET['force-check'] ) ) ) {
		return true;
	}

	// phpcs:ignore WordPress.Security.NonceVerification.Recommended
	if ( isset( $_GET['force-check'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( (string) $_GET['force-check'] ) ), 'dsm-force-check' ) ) {
		return true;
	}

	return false;
}

/**
 * V2.0
 */
class Woo_DS_PluginUpdate {
	public $api_url;
	private $slug;
	public $plugin;
	private $API_VERSION;

	/**
	 * One remote GET per distinct request URL per PHP request (core may call `pre_set_site_transient_update_plugins` several times).
	 *
	 * @var array<string, array<string, mixed>|\WP_Error>
	 */
	private static $remote_response_by_uri_key = array();

	public function __construct( $api_url, $slug, $plugin ) {
		$this->api_url = $api_url;

		$this->slug   = $slug;
		$this->plugin = $plugin;

		// use laets available API.
		$this->API_VERSION = 1.2;

	}


	/**
	 * @param object               $checked_data Transient value being saved.
	 * @param int|null             $expiration   Transient TTL (unused).
	 * @param string               $name         Transient name (unused).
	 * @return object
	 */
	public function check_for_plugin_update( $checked_data, $expiration = null, $name = '' ) {
		if ( ! is_object( $checked_data ) ) {
			return $checked_data;
		}

		// Core always sets `response`; normalize so we can merge. Update URI may also fill `no_update` for this plugin.
		if ( ! isset( $checked_data->response ) || ! is_array( $checked_data->response ) ) {
			$checked_data->response = array();
		}

		$request_string = $this->prepare_request( 'plugin_update' );
		if ( false === $request_string ) {
			return $checked_data;
		}

		$DSM_PRO_licence = new DSM_PRO_licence();
		$licence_data    = $DSM_PRO_licence->get_licence_data();

		if ( isset( $licence_data['key'] ) && true === empty( $licence_data['key'] ) ) {
			return $checked_data;
		}
		// Start checking for an update.
		$request_uri = $this->api_url . '?' . http_build_query( $request_string, '', '&' );

		$data = $this->get_remote_api_response( $request_uri );

		if ( is_wp_error( $data ) ) {
			return $checked_data;
		}

		$response_code = wp_remote_retrieve_response_code( $data );

		if ( 200 !== (int) $response_code ) {
			return $checked_data;
		}

		$response_block = json_decode( $data['body'] );

		if ( ! is_array( $response_block ) || count( $response_block ) < 1 ) {
			return $checked_data;
		}

		// retrieve the last message within the $response_block.
		$response_block = $response_block[ count( $response_block ) - 1 ];
		$response       = $this->extract_plugin_update_object_from_api_row( $response_block );

		if ( is_object( $response ) && ! empty( (array) $response ) ) {
			$response = $this->postprocess_response( $response );

			if ( isset( $checked_data->no_update ) && is_object( $checked_data->no_update ) ) {
				$checked_data->no_update = (array) $checked_data->no_update;
			}

			if ( is_array( $checked_data->no_update ?? null ) && isset( $checked_data->no_update[ $this->plugin ] ) ) {
				unset( $checked_data->no_update[ $this->plugin ] );
			}

			$checked_data->response[ $this->plugin ] = $response;
		}

		return $checked_data;
	}


	public function plugins_api_call( $def, $action, $args ) {
		if ( ! is_object( $args ) || ! isset( $args->slug ) || $args->slug !== $this->slug ) {
			return $def;
		}

		$request_string = $this->prepare_request( $action, $args );
		if ( false === $request_string ) {
			return new WP_Error( 'plugins_api_failed', __( 'An error occour when try to identify the pluguin.', 'software-license' ) . '&lt;/p> &lt;p>&lt;a href=&quot;?&quot; onclick=&quot;document.location.reload(); return false;&quot;>' . __( 'Try again', 'software-license' ) . '&lt;/a>' );
		}

		$DSM_PRO_licence = new DSM_PRO_licence();
		$licence_data    = $DSM_PRO_licence->get_licence_data();

		if ( isset( $licence_data['key'] ) && true === empty( $licence_data['key'] ) ) {
			return;
		}
		$request_uri = $this->api_url . '?' . http_build_query( $request_string, '', '&' );

		$data = $this->get_remote_api_response( $request_uri );

		if ( is_wp_error( $data ) ) {
			return new WP_Error( 'plugins_api_failed', __( 'An Unexpected HTTP Error occurred during the API request.', 'software-license' ) . '&lt;/p> &lt;p>&lt;a href=&quot;?&quot; onclick=&quot;document.location.reload(); return false;&quot;>' . __( 'Try again', 'software-license' ) . '&lt;/a>', $data->get_error_message() );
		}

		$response_code = wp_remote_retrieve_response_code( $data );

		if ( 200 !== (int) $response_code ) {
			return new WP_Error( 'plugins_api_failed', __( 'An Unexpected HTTP Error occurred during the API request.', 'software-license' ) . '&lt;/p> &lt;p>&lt;a href=&quot;?&quot; onclick=&quot;document.location.reload(); return false;&quot;>' . __( 'Try again', 'software-license' ) . '&lt;/a>', (string) $response_code );
		}

		$response_block = json_decode( $data['body'] );
		// retrieve the last message within the $response_block.
		$response_block = $response_block[ count( $response_block ) - 1 ];
		$response       = $this->extract_plugin_update_object_from_api_row( $response_block );

		if ( is_object( $response ) && ! empty( (array) $response ) ) {
			$response = $this->postprocess_response( $response );

			return $response;
		}
	}

	/**
	 * API returns either legacy `message` (object with update fields) or `update_data` plus a string `message`.
	 *
	 * @param object $row Last decoded object from the API JSON array.
	 * @return object|null Update payload for WordPress, or null.
	 */
	private function extract_plugin_update_object_from_api_row( $row ) {
		if ( ! is_object( $row ) ) {
			return null;
		}

		if ( isset( $row->update_data ) ) {
			$ud = $row->update_data;
			if ( is_array( $ud ) ) {
				$ud = (object) $ud;
			}
			if ( is_object( $ud ) ) {
				$new_version = isset( $ud->new_version ) ? trim( (string) $ud->new_version ) : '';
				$package     = isset( $ud->package ) ? trim( (string) $ud->package ) : '';
				if ( '' !== $new_version && '' !== $package ) {
					return $ud;
				}
			}
		}

		$msg = isset( $row->message ) ? $row->message : null;
		if ( is_object( $msg ) && ! empty( (array) $msg ) ) {
			return $msg;
		}

		return null;
	}

	/**
	 * Fetch (or reuse) the raw HTTP response for a licence API URL.
	 *
	 * @param string $request_uri Full URL with query string.
	 * @return array<string, mixed>|\WP_Error
	 */
	private function get_remote_api_response( $request_uri ) {
		$key = md5( $request_uri );

		if ( array_key_exists( $key, self::$remote_response_by_uri_key ) ) {
			return self::$remote_response_by_uri_key[ $key ];
		}

		global $wp_version;

		$transient_key = 'divisupremepro-check_for_plugin_update_' . $key;
		$data          = get_site_transient( $transient_key );

		if ( dsm_plugin_updater_should_bust_http_cache() ) {
			$data = false;
		}

		if ( false === $data ) {
			$data = wp_safe_remote_get(
				$request_uri,
				array(
					'timeout'    => 20,
					'user-agent' => 'WordPress/' . $wp_version . '; DiviSupremePro/' . DSM_PRO_VERSION . '; ' . DSM_PRO_INSTANCE,
				)
			);

			$response_code = wp_remote_retrieve_response_code( $data );

			if ( ! is_wp_error( $data ) && 200 === (int) $response_code ) {
				set_site_transient( $transient_key, $data, 60 * 60 * 4 );
			}
		}

		self::$remote_response_by_uri_key[ $key ] = $data;

		return $data;
	}

	private function prepare_request( $action, $args = array() ) {
		global $wp_version;
		$DSM_PRO_licence = new DSM_PRO_licence();
		$licence_data    = $DSM_PRO_licence->get_licence_data();
		/*
		$license_data = get_site_option( 'dsm_pro_license' );
		$license_data_key;
		if ( ! isset( $license_data['key'] ) ) {
			$license_data_key = '';
		} else {
			$license_data_key = $license_data['key'];
		}
		*/
		return array(
			'woo_sl_action'     => $action,
			'version'           => DSM_PRO_VERSION,
			'product_unique_id' => DSM_PRODUCT_ID,
			'licence_key'       => $licence_data['key'],
			'domain'            => DSM_PRO_INSTANCE,
			'wp-version'        => $wp_version,
			'api_version'       => $this->API_VERSION,

		);
	}


	private function postprocess_response( $response ) {
		// include slug and plugin data.
		$response->slug   = $this->slug;
		$response->plugin = $this->plugin;

		if ( empty( $response->url ) && ! empty( $response->homepage ) ) {
			$response->url = $response->homepage;
		}

		// if sections are being set.
		if ( isset( $response->sections ) ) {
			$response->sections = (array) $response->sections;
		}

		// if banners are being set.
		if ( isset( $response->banners ) ) {
			$response->banners = (array) $response->banners;
		}

		// if icons being set, convert to array.
		if ( isset( $response->icons ) ) {
			$response->icons = (array) $response->icons;
		}

		return $response;

	}


	function in_plugin_update_message( $plugin_data, $response ) {
		if ( empty( $response->upgrade_notice ) ) {
			return;
		}

		echo esc_html( $response->upgrade_notice );

	}
}

function Woo_DS_run_updater() {
	$wp_plugin_auto_update = new Woo_DS_PluginUpdate( DSM_PRO_APP_API_URL, 'supreme-modules-pro-for-divi', 'supreme-modules-pro-for-divi/supreme-modules-pro-for-divi.php' );

	/*
	 * Run late so WordPress Update URI / core merge finishes first; we then override with the license API result
	 * and clear any incorrect `no_update` entry for this plugin.
	 */
	add_filter( 'pre_set_site_transient_update_plugins', array( $wp_plugin_auto_update, 'check_for_plugin_update' ), 999, 3 );

	// Take over the Plugin info screen.
	add_filter( 'plugins_api', array( $wp_plugin_auto_update, 'plugins_api_call' ), 99, 3 );

	add_action( 'in_plugin_update_message-supreme-modules-pro-for-divi/supreme-modules-pro-for-divi.php', array( $wp_plugin_auto_update, 'in_plugin_update_message' ), 10, 2 );

}

if ( ! defined( 'DSM_DEFER_STABLE_PLUGIN_UPDATER' ) || false === DSM_DEFER_STABLE_PLUGIN_UPDATER ) {
	add_action( 'after_setup_theme', 'Woo_DS_run_updater' );
}
