<?php
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

class Cev_Pro_License {
	
	/**
	 * Instance of this class.
	 *
	 * @var object Class Instance
	*/
	private static $instance;

	/**
	 * Item code for the license.
	 * 
	 * @var string
	*/
	public $item_code = 'cev_pro';

	/**
	 * Store URL for license validation.
	 * 
	 * @var string
	*/
	public $store_url = 'https://www.zorem.com/';

	/**
	 * Default product ID.
	 * 
	 * @var string
	*/
	public $default_product_id = '90012';

	/**
	 * Get the singleton instance of this class.
	 *
	 * Ensures that only one instance of the class is created.
	 *
	 * @since  1.0
	 * @return CEV_License
	*/
	public static function get_instance() {
		if ( null === self::$instance ) {
			self::$instance = new self();
		}
		return self::$instance;
	}

	/**
	 * Constructor function.
	 *
	 * Initializes the license management functionality.
	 *
	 * @since  1.0
	 */
	public function __construct() {        
		$this->init();
	}

	/**
	 * Get the item code for the license.
	 *
	 * @since   1.0
	 * @return  string Item code.
	 */
	public function get_item_code() {
		return $this->item_code;
	}

	/**
	 * Set the license key in the database.
	 *
	 * @since   1.0
	 * @param   string $license_key License key to be saved.
	 * @return  void
	 */
	public function set_license_key( $license_key ) {
		update_option( $this->get_item_code() . '_license_key', $license_key );
	}

	/**
	 * Retrieve the stored license key.
	 *
	 * @since   1.0
	 * @return  string|false License key or false if not found.
	 */
	public function get_license_key() {
		return get_option( $this->get_item_code() . '_license_key', false );
	}

	/**
	 * Set the license status in the database.
	 *
	 * @since   1.0
	 * @param   string $status License status (e.g., active, inactive).
	 * @return  void
	 */
	public function set_license_status( $status ) {
		update_option( $this->get_item_code() . '_license_status', $status );
	}

	/**
	 * Retrieve the stored license status.
	 *
	 * @since   1.0
	 * @return  string|false License status or false if not found.
	 */
	public function get_license_status() {
		return get_option( $this->get_item_code() . '_license_status', false );
	}

	/**
	 * Generate a unique instance ID.
	 *
	 * This is used to uniquely identify the installation.
	 *
	 * @since   1.0
	 * @return  string Generated instance ID.
	 */
	public function create_instance_id() {
		$instance_id = md5( $this->get_item_code() . time() );
		return $instance_id;
	}

	/**
	 * Store the generated instance ID in the database.
	 *
	 * @since   1.0
	 * @param   string $instance_id Instance ID to be stored.
	 * @return  void
	 */
	public function set_instance_id( $instance_id ) {
		update_option( $this->get_item_code() . '_instance_id', $instance_id );
	}

	/**
	 * Retrieve the stored instance ID.
	 *
	 * @since   1.0
	 * @return  string|false Instance ID or false if not found.
	 */
	public function get_instance_id() {
		return get_option( $this->get_item_code() . '_instance_id', false );
	}

	/**
	 * Get the default product ID.
	 *
	 * @since   1.0
	 * @return  string Default product ID.
	 */
	public function get_product_id() {
		return $this->default_product_id;
	}

	/**
	 * Get the license cron job hook name.
	 *
	 * This hook is used for scheduling license validation.
	 *
	 * @since   1.0
	 * @return  string Cron hook name.
	 */
	public function get_license_cron_hook() {
		return $this->get_item_code() . '_license_cron_hook';
	}
	
	/**
	 * Initialize the license management functionality.
	 *
	 * This function sets up cron schedules, AJAX handlers,
	 * license validation checks, and admin scripts.
	 *
	 * @since  1.0
	 */
	public function init() {
		
		// Add a custom cron schedule for license validation.
		add_filter( 'cron_schedules', array( $this, 'license_cron_schedule') );
		
		// Register AJAX actions for license activation and deactivation.
		add_action( 'wp_ajax_' . $this->get_item_code() . '_license_activate', array( $this, 'license_activate') );
		add_action( 'wp_ajax_' . $this->get_item_code() . '_license_deactivate', array( $this, 'license_deactivate') );
		
		// Handle regular POST form submissions for license deactivation.
		add_action( 'admin_init', array( $this, 'handle_license_form_submission') );
		
		// Schedule the license validation cron job.
		add_action( 'admin_init', array( $this, 'add_cron_schedule') );

		// Hook the license validation function to the cron schedule.
		add_action( $this->get_license_cron_hook(), array( $this, 'check_license_valid' ) );
		
		// Show an admin notice if the license is not activated.
		if ( ! $this->get_license_status() ) {
			add_action( 'admin_notices', array( $this, 'cev_pro_item_licence_notice') );
		}

		// Hook for adding license-related settings in the admin panel.
		add_action( 'cev_license_tab_content_data_array', array( $this, 'connect_with_zorem' ) );
		
		// Load JavaScript and CSS for the admin panel.
		add_action( 'admin_enqueue_scripts', array( $this, 'admin_styles' ), 20);

		add_action( "{$this->item_code}_check_subscription_daily", array( $this, 'cron_refresh_subscription_status' ) );
		add_action( "{$this->item_code}_check_subscription_single", array( $this, 'cron_refresh_subscription_status' ) );
	}
	
	/**
	 * Load admin styles and scripts.
	 *
	 * This function ensures that the license-related styles
	 * are only loaded on the correct admin page.
	 *
	 * @since 1.0
	 * @param string $hook The current admin page hook.
	 */
	public function admin_styles( $hook ) {
		// Exit if the 'page' query parameter is not set.
		if ( ! isset( $_GET['page'] ) ) {
			return;
		}

		// Load styles only on the Customer Email Verification plugin settings page.
		if ( 'customer-email-verification-for-woocommerce' !== $_GET['page'] ) {
			return;
		}

		// Enqueue the license management CSS file.
		wp_enqueue_style( 'cev-pro-license-css', cev_pro()->plugin_dir_url() . 'assets/css/license.css', array(), cev_pro()->version );
	}

	/**
	 * Add a custom cron schedule for license validation.
	 *
	 * This schedule runs every 24 hours to check the license status.
	 *
	 * @since  1.0
	 * @param  array $schedules The existing WordPress cron schedules.
	 * @return array Modified cron schedules including license check.
	 */
	public function license_cron_schedule( $schedules ) {
		$schedules['license_cron_events'] = array(
			'interval' => 86400, // 24 hours
			'display'  => __( 'Every day', 'customer-email-verification' ),
		);
		return $schedules;
	}

	/**
	 * Handle AJAX request for license activation.
	 *
	 * This function verifies the AJAX request, retrieves the license key,
	 * sends an activation request, and updates the license status accordingly.
	 *
	 * @since  1.0
	 */
	public function license_activate() {
		// Verify nonce to ensure the request is legitimate.
		check_ajax_referer( 'wc_cev_addons_form', 'wc_cev_addons_form_nonce' );

		// Get and sanitize the license key from the request.
		$license_key = isset( $_POST['license_key'] ) ? sanitize_text_field( $_POST['license_key'] ) : '';

		if ( ! empty( $license_key ) ) {
			// Generate a unique instance ID for this activation.
			$instance_id = $this->create_instance_id();

			// Send the license activation request.
			$authorize_data = $this->license_authorize_action( $license_key, 'activate', $instance_id );

			if ( isset( $authorize_data->success ) && 'true' === $authorize_data->success ) {
				// Store license details if activation is successful.
				$this->set_license_key( $license_key );
				$this->set_instance_id( $instance_id );
				$this->set_license_status( 1 );
				delete_transient( 'zorem_upgrade_' . $this->get_item_code() );
				$this->force_refresh_subscription_status_async();
			} elseif ( isset( $authorize_data->error ) ) {
				// Reset license details if activation fails.
				$this->create_log( $authorize_data, 'license_activation_authorize_data' );
				$this->set_license_key( '' );
				$this->set_instance_id( '' );
				$this->set_license_status( 0 );
			}

			// Return JSON response.
			header( 'Content-type: application/json' );
			echo json_encode( $authorize_data, JSON_PRETTY_PRINT );
			die();
		}       
	}

	/**
	 * Deactivate the license via AJAX request.
	 *
	 * This function verifies the nonce, sanitizes the input,
	 * and sends a request to the license server to deactivate the license.
	 *
	 * @since 1.0
	 * @return void Outputs JSON response.
	 */
	public function license_deactivate() {
		// Verify the nonce for security.
		check_ajax_referer( 'wc_cev_addons_form', 'wc_cev_addons_form_nonce' );

		// Sanitize the input license key.
		$license_key = isset( $_POST['license_key'] ) ? sanitize_text_field( $_POST['license_key'] ) : '';

		if ( ! empty( $license_key ) ) {
			// Send the deactivate request.
			$return = $this->license_authorize_action( $license_key, 'deactivate' );

			if ( 'true' == $return->success || '' == $return->success ) {
				// Reset license details on successful deactivation.
				$this->set_license_key( '' );
				$this->set_instance_id( '' );
				$this->set_license_status( 0 );
				delete_transient( 'zorem_upgrade_' . $this->get_item_code() );
				$this->force_refresh_subscription_status_async();
			}

			// Return the response in JSON format.
			header( 'Content-type: application/json' );
			echo json_encode( $return, JSON_PRETTY_PRINT );
			die();
		}
	}

	/**
	 * Handle regular POST form submissions for license activation/deactivation.
	 *
	 * This function processes form submissions (non-AJAX) for license operations.
	 *
	 * @since 1.0
	 * @return void Redirects back to the license page.
	 */
	public function handle_license_form_submission() {
		// Only process if this is a POST request and we're on the admin page.
		if ( ! isset( $_POST['action'] ) || ! isset( $_POST['wc_cev_addons_form_nonce'] ) ) {
			return;
		}

		// Verify the nonce for security.
		if ( ! wp_verify_nonce( $_POST['wc_cev_addons_form_nonce'], 'wc_cev_addons_form' ) ) {
			return;
		}

		$action = sanitize_text_field( $_POST['action'] );
		$deactivate_action = $this->get_item_code() . '_license_deactivate';
		$activate_action = $this->get_item_code() . '_license_activate';

		// Handle license deactivation.
		if ( $action === $deactivate_action ) {
			$license_key = isset( $_POST['license_key'] ) ? sanitize_text_field( $_POST['license_key'] ) : '';

			if ( ! empty( $license_key ) ) {
				// Send the deactivate request.
				$return = $this->license_authorize_action( $license_key, 'deactivate' );

				if ( 'true' == $return->success || '' == $return->success ) {
					// Reset license details on successful deactivation.
					$this->set_license_key( '' );
					$this->set_instance_id( '' );
					$this->set_license_status( 0 );
					delete_transient( 'zorem_upgrade_' . $this->get_item_code() );
					$this->force_refresh_subscription_status_async();
				}

				// Redirect back to the license page.
				$redirect_url = admin_url( '/admin.php?page=customer-email-verification-for-woocommerce&tab=add-ons' );
				wp_safe_redirect( $redirect_url );
				exit;
			}
		}
		// Handle license activation (if needed in the future).
		elseif ( $action === $activate_action ) {
			$license_key = isset( $_POST['license_key'] ) ? sanitize_text_field( $_POST['license_key'] ) : '';

			if ( ! empty( $license_key ) ) {
				// Generate a unique instance ID for this activation.
				$instance_id = $this->create_instance_id();

				// Send the license activation request.
				$authorize_data = $this->license_authorize_action( $license_key, 'activate', $instance_id );

				if ( isset( $authorize_data->success ) && 'true' === $authorize_data->success ) {
					// Store license details if activation is successful.
					$this->set_license_key( $license_key );
					$this->set_instance_id( $instance_id );
					$this->set_license_status( 1 );
					delete_transient( 'zorem_upgrade_' . $this->get_item_code() );
					$this->force_refresh_subscription_status_async();
				}

				// Redirect back to the license page.
				$redirect_url = admin_url( '/admin.php?page=customer-email-verification-for-woocommerce&tab=add-ons' );
				wp_safe_redirect( $redirect_url );
				exit;
			}
		}
	}

	/**
	 * Authorize license action with the server.
	 *
	 * This function sends API requests to activate, deactivate,
	 * or validate licenses.
	 *
	 * @since 1.0
	 * @param string $license_key License key.
	 * @param string $action Action type (activate, deactivate, validate).
	 * @param string|false $instance_id Unique installation ID.
	 * @return object|false API response or false on failure.
	 */
	public function license_authorize_action( $license_key = '', $action = 'validate', $instance_id = false ) {
		if ( false === $instance_id ) {
			$instance_id = $this->get_instance_id();
		}

		$domain = home_url();

		$api_params = array(
			'wc-api'        => 'wc-am-api',
			'wc_am_action'  => $action,
			'instance'      => $instance_id,
			'object'        => $domain,
			'product_id'    => $this->get_product_id(),
			'api_key'       => $license_key,
		);

		$request = add_query_arg( $api_params, $this->store_url );
		$response = wp_remote_get( $request, array( 'timeout' => 15, 'sslverify' => false ) );

		if ( is_wp_error( $response ) ) {
			$this->create_log( $response, 'license_activation_response' );
			return false;
		}

		$authorize_data = json_decode( wp_remote_retrieve_body( $response ) );

		if ( empty( $authorize_data ) || null == $authorize_data || false == $authorize_data ) {
			$this->create_log( $authorize_data, 'license_activation_authorize_data' );
			return false;
		}

		return $authorize_data;
	}

	/**
	 * Schedule cron event for license validation if not already scheduled.
	 *
	 * @since 1.0
	 * @return void
	 */
	public function add_cron_schedule() {
		if ( ! wp_next_scheduled( $this->get_license_cron_hook() ) ) {
			wp_schedule_event( time(), 'license_cron_events', $this->get_license_cron_hook() );
		}
	}

	/**
	 * Validate the license via scheduled cron job.
	 *
	 * If the license is inactive or invalid, the license details will be reset.
	 *
	 * @since 1.0
	 * @return void
	 */
	public function check_license_valid() {
		if ( $this->get_license_status() ) {
			$authorize = $this->license_authorize_action( $this->get_license_key(), 'status' );

			if ( 'true' == $authorize->success ) {
				if ( isset( $authorize->status_check ) && 'inactive' == $authorize->status_check ) {
					$this->set_license_key( '' );
					$this->set_instance_id( '' );
					$this->set_license_status( 0 );
				}
			} elseif ( 'false' == $authorize->success ) {
				$this->set_license_key( '' );
				$this->set_instance_id( '' );
				$this->set_license_status( 0 );
			}
		}
	}

	/**
	 * Display admin notice if the license is not activated.
	 *
	 * @since 1.0
	 * @return void
	 */
	public function cev_pro_item_licence_notice() { 
		$class = 'notice notice-error';
		/* translators: %s: Customer Email Verification PRO */
		$message = sprintf( __( 'Oops! Your <strong>Customer Email Verification PRO</strong> license key is not activated. To buy a license %1$sclick here%2$s to activate it.', 'customer-email-verification-pro' ), '<a href="' . esc_url( admin_url( '/admin.php?page=customer-email-verification-for-woocommerce&tab=add-ons' ) ) . '">', '</a>' );
		echo wp_kses_post( '<div class="' . esc_attr( $class ) . ' cev-pro-license-notice"><p>' . $message . '</p></div>' );
	}
	public function connect_with_zorem() {		
		
		$connect = isset( $_GET['connect'] ) ? sanitize_text_field( $_GET['connect'] ) : '';
		$email = isset( $_GET['email'] ) ? sanitize_text_field( $_GET['email'] ) : '';
		$license_key = isset( $_GET['key'] ) ? sanitize_text_field( $_GET['key'] ) : '';
		//echo '<pre>';print_r($_GET);echo '</pre>';
		?>
		<script>
			/* zorem_snackbar jquery */
			(function( $ ){
				$.fn.cev_snackbar = function(msg) {
					if ( jQuery('.snackbar-logs').length === 0 ){
						$("body").append("<section class=snackbar-logs></section>");
					}
					var cev_snackbar = $("<article></article>").addClass('snackbar-log snackbar-log-success snackbar-log-show').text( msg );
					$(".snackbar-logs").append(cev_snackbar);
					setTimeout(function(){ cev_snackbar.remove(); }, 3000);
					return this;
				}; 
			})( jQuery );
			
			/* zorem_snackbar_warning jquery */
			(function( $ ){
				$.fn.cev_snackbar_warning = function(msg) {
					if ( jQuery('.snackbar-logs').length === 0 ){
						$("body").append("<section class=snackbar-logs></section>");
					}
					var cev_snackbar_warning = $("<article></article>").addClass( 'snackbar-log snackbar-log-error snackbar-log-show' ).html( msg );
					$(".snackbar-logs").append(cev_snackbar_warning);
					setTimeout(function(){ cev_snackbar_warning.remove(); }, 3000);
					return this;
				}; 
			})( jQuery );
		</script>
		<?php
		if ( 'true' == $connect && '' != $email ) {
			update_option( 'zorem_license_connected', 1 );
			update_option( 'zorem_license_email', $email );
			

			if ( isset( $license_key ) ) {
				$instance_id = $this->create_instance_id();
				$authorize_data = $this->license_authorize_action( $license_key, 'activate', $instance_id );
				
				if ( 'true' == $authorize_data->success ) {
					$this->set_license_key( $license_key );
					$this->set_instance_id( $instance_id );
					$this->set_license_status( 1 );
					update_option( 'zorem_license_key', $license_key );
					delete_transient( 'zorem_upgrade_' . $this->get_item_code() );
					$message = 'License successfully activated.';
					?>
					<script>
						jQuery(document).cev_snackbar( '<?php esc_html_e( $message ); ?>' );
					</script>
					<style>
					.cev-pro-license-notice {
						display: none;
					}
					</style>
					<?php
				} else if ( $authorize_data->error ) {
					$this->create_log( $authorize_data, 'license_activation_authorize_data' );
					if ( 'No API resources exist. Login to My Account to verify there are activations remaining, and the API Key and Product ID are correct.' == $authorize_data->error ) {
						$message = 'License not found for user ' . $email;
						?>
						<script>
							jQuery(document).cev_snackbar_warning( '<?php esc_html_e( $message ); ?>' );
						</script>
						<?php	
					} elseif ( 'Cannot activate License Key. This key is already active on another site.' == $authorize_data->error ) {
						$message = 'Cannot activate License. License is already active on another site.';
						?>
						<script>
							jQuery(document).cev_snackbar_warning( '<?php esc_html_e( $message ); ?>' );
						</script>
						<?php
					} else {
						$message = 'License not found for user ' . $email;
						?>
						<script>
							jQuery(document).cev_snackbar_warning( '<?php esc_html_e( $message ); ?>' );
						</script>
						<?php
					}
					
					$this->set_license_key( '' );
					$this->set_instance_id( '' );
					$this->set_license_status( 0 );
				}
			}	
			?>
			<script>
				var url = window.location.protocol + "//" + window.location.host + window.location.pathname+"?page=customer-email-verification-for-woocommerce&tab=add-ons";
				window.history.pushState({path:url},'',url);
				jQuery('input#Add_tab').trigger('click');
				location.reload();
			</script>
			<?php
		} elseif ( 'false' == $connect && '' != $email ) {
			?>
			<script>
				var url = window.location.protocol + "//" + window.location.host + window.location.pathname+"?page=customer-email-verification-for-woocommerce&tab=add-ons";
				window.history.pushState({path:url},'',url);
				jQuery('input#Add_tab').trigger('click');
				location.reload();
			</script>
			<?php	
		}

		$this->force_refresh_subscription_status_async();
	}
	protected function get_cache_option_name() {
		return 'zorem_subscription_cache_' . $this->get_item_code();
	}
	public function check_subscription_status() {

		// If your own "license status" shortcut is already true, keep it.
		if ( $this->get_license_status() ) {
			return true;
		}
		
		$license_connected = (int) get_option( 'zorem_license_connected', 0 );
		$license_email     = (string) get_option( 'zorem_license_email', '' );

		// If not connected yet, don't show Pro features
		if ( ! $license_connected && '' === $license_email ) {
			return false;
		}

		$cache = get_option( $this->get_cache_option_name(), null );

		// If we have no cache yet, schedule a quick async refresh and default to true or false.
		// I recommend defaulting to TRUE to avoid accidental lockouts during first run.
		if ( ! is_array( $cache ) ) {

			// Kick a single-run refresh soon
			$this->force_refresh_subscription_status_async();

			$default = true;
			return (bool) $default;
		}

		$subscription = isset( $cache['subscription'] ) ? (bool) $cache['subscription'] : false;
		$checked_at   = isset( $cache['checked_at'] ) ? (int) $cache['checked_at'] : 0;

		// If cache is older than 36h, schedule a non-blocking refresh (but still use last-known value now)
		if ( ( time() - $checked_at ) > DAY_IN_SECONDS + 12 * HOUR_IN_SECONDS ) {
			$this->force_refresh_subscription_status_async();
		}

		return $subscription;
	}
	public function force_refresh_subscription_status_async() {
		// Fire a one-off refresh soon (non-blocking)
		$hook = "{$this->item_code}_check_subscription_single";

		if ( ! wp_next_scheduled( $hook ) ) {
			wp_schedule_single_event( time() + 60, $hook );
		}
	}
	public function cron_refresh_subscription_status() {
		$license_connected = get_option( 'zorem_license_connected', 0 );
		$license_email     = get_option( 'zorem_license_email', '' );

		if ( ! $license_connected && '' === $license_email ) {
			// No connection yet; store a neutral cache
			update_option( $this->get_cache_option_name(), [
				'subscription' => false,
				'checked_at'   => time(),
				'error'        => null,
			], false );
			return;
		}

		$api_params = [
			'license_email' => $license_email,
			'product_id'    => $this->get_product_id(),
		];

		$url      = add_query_arg( $api_params, $this->store_url . 'wp-json/wc-zorem-license/v3/status/subscription' );
		$request  = esc_url_raw( $url );
		
		$plugin_version = ! empty( cev_pro()->version ) ? cev_pro()->version : 'unknown';
		$site_url       = home_url();

		$response = wp_safe_remote_get( $request, [
			'timeout'   => 2,
			'sslverify' => true,
			'headers'   => [
				'User-Agent' => 'Zorem-CEV/Pro ' . $plugin_version . ' (' . $site_url . ')',
				'Accept'     => 'application/json',
			],
		] );

		$cache       = get_option( $this->get_cache_option_name(), null );
		$last_known  = is_array( $cache ) && array_key_exists( 'subscription', $cache ) ? (bool) $cache['subscription'] : false;

		if ( is_wp_error( $response ) ) {
			// Keep last known and record error
			update_option( $this->get_cache_option_name(), [
				'subscription' => $last_known,
				'checked_at'   => time(),
				'error'        => $response->get_error_message(),
			], false );
			return;
		}

		$code = wp_remote_retrieve_response_code( $response );
		$body = wp_remote_retrieve_body( $response );

		if ( 200 !== (int) $code || true === empty( $body ) ) {
			update_option( $this->get_cache_option_name(), [
				'subscription' => $last_known,
				'checked_at'   => time(),
				'error'        => 'HTTP ' . $code . ' or empty body',
			], false );
			return;
		}

		$data = json_decode( $body );

		// Defensive parsing
		$subscription_flag = ( is_object( $data ) && property_exists( $data, 'subscription' ) )
			? (bool) $data->subscription
			: $last_known;

		update_option( $this->get_cache_option_name(), [
			'subscription' => $subscription_flag,
			'checked_at'   => time(),
			'error'        => null,
		], false );
	}
	public function create_log( $content, $log_key = 'license_activation_authorize_data' ) {
		$content = print_r($content, true);
		$logger = wc_get_logger();
		$context = array( 'source' => 'cev_pro_license_activation_log' );
		$logger->info( $log_key . " \n" . $content . "\n", $context );
	}

}
