<?php
/**
 * Version Pilot Client Updater
 *
 * This file should be included in your plugin to enable updates from your Version Pilot server.
 *
 * @version 1.0.0
 *
 * --- USAGE ---
 *
 * 1. Include this file in your plugin.
 * require_once 'path/to/version-pilot-client-updater.php';
 *
 * 2. Instantiate the class.
 * new Version_Pilot_Client_Updater(
 * 'https://your-domain.com',       // Your website URL where Version Pilot is installed.
 * 'your-plugin-slug',              // The unique slug of your plugin.
 * plugin_basename( __FILE__ ),     // Your plugin's main file path (e.g., your-plugin/your-plugin.php).
 * '1.0.0'                          // The CURRENT version of your plugin.
 * );
 *
 */

if ( ! class_exists( 'Version_Pilot_Client_Updater' ) ) :

	class Version_Pilot_Client_Updater {

		/**
		 * The API URL of the author's server.
		 *
		 * @var string
		 */
		private $api_url;

		/**
		 * The slug of the plugin.
		 *
		 * @var string
		 */
		private $plugin_slug;

		/**
		 * The plugin's basename (e.g., my-plugin/my-plugin.php).
		 *
		 * @var string
		 */
		private $plugin_basename;

		/**
		 * The current version of the plugin.
		 *
		 * @var string
		 */
		private $current_version;

		/**
		 * Class constructor.
		 *
		 * @param string $api_url         The URL of the Version Pilot server.
		 * @param string $plugin_slug     The slug of this plugin.
		 * @param string $plugin_basename The basename of this plugin.
		 * @param string $current_version The current version of this plugin.
		 */
		public function __construct( $api_url, $plugin_slug, $plugin_basename, $current_version ) {
			$this->api_url         = rtrim( $api_url, '/' );
			$this->plugin_slug     = $plugin_slug;
			$this->plugin_basename = $plugin_basename;
			$this->current_version = $current_version;
			
			// Hook into the update check process.
			add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_for_updates' ) );
			// Hook into the plugin information screen.
			add_filter( 'plugins_api', array( $this, 'plugin_information' ), 10, 3 );
		}

		/**
		 * Check for plugin updates.
		 *
		 * @param object $transient The update transient.
		 * @return object The modified transient.
		 */
		public function check_for_updates( $transient ) {
			if ( empty( $transient->checked ) ) {
				return $transient;
			}

			$remote_info = $this->get_remote_info();

			if ( $remote_info && isset( $remote_info->version ) && version_compare( $this->current_version, $remote_info->version, '<' ) ) {
				$update_obj              = new \stdClass();
				$update_obj->slug        = $this->plugin_slug;
				$update_obj->plugin      = $this->plugin_basename;
				$update_obj->new_version = $remote_info->version;
				$update_obj->url         = $remote_info->homepage;
				$update_obj->package     = $remote_info->package;

				$transient->response[ $this->plugin_basename ] = $update_obj;
			}

			return $transient;
		}

		/**
		 * Provide plugin information for the "View details" screen.
		 *
		 * @param false|object|array $result The result object.
		 * @param string             $action The type of information being requested.
		 * @param object             $args   Plugin API arguments.
		 * @return false|object The modified result object or false.
		 */
		public function plugin_information( $result, $action, $args ) {
			// Check if this is a request for our plugin.
			if ( 'plugin_information' !== $action || ! isset( $args->slug ) || $args->slug !== $this->plugin_slug ) {
				return $result;
			}

			$remote_info = $this->get_remote_info();

			if ( $remote_info ) {
				// The remote info is already in the correct format.
				return $remote_info;
			}

			return $result;
		}

		/**
		 * Retrieve remote plugin information from the API.
		 *
		 * @return object|false The plugin information object or false on failure.
		 */
		private function get_remote_info() {
			$transient_key = 'version_pilot_update_' . $this->plugin_slug;
			$cached_info = get_site_transient( $transient_key );

			if ( false !== $cached_info ) {
				return $cached_info;
			}

			/**
			 * Filter to provide authentication credentials for the update request.
			 *
			 * @since 1.0.0
			 * @param array  $credentials {
			 * An array of credentials.
			 *
			 * @type string $user The username or member ID.
			 * @type string $key  The API key or license key.
			 * }
			 * @param string $plugin_slug The slug of the plugin being updated.
			 */
			$credentials = apply_filters(
				'version_pilot_client_auth_credentials',
				array(
					'user' => '',
					'key'  => '',
				),
				$this->plugin_slug
			);

			$local_site_host  = wp_parse_url( home_url(), PHP_URL_HOST );
			$client_api_host  = wp_parse_url( $this->api_url, PHP_URL_HOST );
			$use_local_method = ( $local_site_host === $client_api_host ) && class_exists( '\Wowown\VersionPilot\Includes\Version_Pilot_REST_API' );

			$remote_info = false;

			if ( $use_local_method ) {
				$api_server = new \Wowown\VersionPilot\Includes\Version_Pilot_REST_API();
				$request    = new \WP_REST_Request( 'GET', '/version-pilot/v1/plugins/' . $this->plugin_slug );
				$request->set_url_params( array( 'slug' => $this->plugin_slug ) );
				$request->set_query_params( array( 'client_version' => $this->current_version ) );

				// Add authentication headers if provided.
				if ( ! empty( $credentials['user'] ) ) {
					$request->set_header( 'x-wvpu-user', $credentials['user'] );
				}
				if ( ! empty( $credentials['key'] ) ) {
					$request->set_header( 'x-wvpu-key', $credentials['key'] );
				}

				$response = $api_server->get_plugin_data( $request );

				if ( is_wp_error( $response ) || ! is_object( $response ) || ! method_exists( $response, 'get_data' ) ) {
					return false;
				}

				$response_data = $response->get_data();
				if ( ! is_array( $response_data ) || empty( $response_data['version'] ) ) {
					return false;
				}

				$remote_info = (object) $response_data;

			} else {
				// If the server class doesn't exist, proceed with the remote HTTP request.
				$request_url = $this->api_url . '/wp-json/version-pilot/v1/plugins/' . $this->plugin_slug;
				$request_url = add_query_arg( 'client_version', $this->current_version, $request_url );
				$args        = array( 'timeout' => 10, 'headers' => array() );

				// Add authentication headers if provided.
				if ( ! empty( $credentials['user'] ) ) {
					$args['headers']['X-Wvpu-User'] = $credentials['user'];
				}
				if ( ! empty( $credentials['key'] ) ) {
					$args['headers']['X-Wvpu-Key'] = $credentials['key'];
				}

				$response = wp_remote_get( $request_url, $args );

				if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) {
					return false;
				}

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

				if ( json_last_error() !== JSON_ERROR_NONE || empty( $remote_info['version'] ) ) {
					return false;
				}

				$remote_info = (object) $remote_info;
			}

			if ( ! is_object( $remote_info ) ) {
				return false;
			}

			// Cache the response for 12 hours.
			set_site_transient( $transient_key, $remote_info, 12 * HOUR_IN_SECONDS );

			return $remote_info;
		}
	}

endif;