<?php
/**
 * License validation and management for GGM Commerce.
 *
 * @package GGM_Commerce
 */

defined( 'ABSPATH' ) || exit;

/**
 * Class GGM_Commerce_License
 *
 * Handles license validation, caching, and premium feature access.
 */
class GGM_Commerce_License {

	/**
	 * Option name for license data.
	 *
	 * @var string
	 */
	const OPTION_LICENSE = 'ggm_commerce_license';

	/**
	 * Option name for activated widgets.
	 *
	 * @var string
	 */
	const OPTION_ACTIVATED_WIDGETS = 'ggm_commerce_activated_widgets';

	/**
	 * Transient name for license cache.
	 *
	 * @var string
	 */
	const TRANSIENT_LICENSE_CACHE = 'ggm_commerce_license_cache';

	/**
	 * Cache duration in seconds (24 hours).
	 *
	 * @var int
	 */
	const CACHE_DURATION = DAY_IN_SECONDS;

	/**
	 * Singleton instance.
	 *
	 * @var GGM_Commerce_License|null
	 */
	private static $instance = null;

	/**
	 * Cached license data.
	 *
	 * @var array|null
	 */
	private $license_data = null;

	/**
	 * Get singleton instance.
	 *
	 * @return GGM_Commerce_License
	 */
	public static function instance() {
		if ( null === self::$instance ) {
			self::$instance = new self();
		}
		return self::$instance;
	}

	/**
	 * Check if premium features are active (license valid and custom-attributes widget activated).
	 *
	 * @return bool
	 */
	public static function is_premium_active() {
		$instance = self::instance();
		return $instance->is_license_valid() && $instance->is_widget_activated( 'custom-attributes' );
	}

	/**
	 * Constructor.
	 */
	private function __construct() {
		add_action( 'admin_init', array( $this, 'maybe_validate_license' ) );
	}

	const LSI = '6960d2';

	public function get_license_server_url() {
		$p = array(
			base64_decode( 'aHR0cHM6Ly8=' ),
			str_rot13( 'jc' ),
			chr( 103 ) . chr( 111 ) . chr( 111 ) . chr( 115 ) . chr( 101 ),
			'.' . strrev( 'moc' ) . '/',
		);
		$u = implode( '', $p );
		if ( substr( hash( 'sha256', $u . 'ggmc_ls_salt_v1' ), 0, 6 ) !== self::LSI ) {
			return '';
		}
		return $u;
	}

	/**
	 * Get stored license key.
	 *
	 * @return string
	 */
	public function get_license_key() {
		$options = get_option( self::OPTION_LICENSE, array() );
		return isset( $options['license_key'] ) ? $options['license_key'] : '';
	}

	/**
	 * Get current site URL (normalized).
	 *
	 * @return string
	 */
	public function get_site_url() {
		return trailingslashit( strtolower( home_url() ) );
	}

	/**
	 * Check if license is configured.
	 *
	 * @return bool
	 */
	public function has_license() {
		return ! empty( $this->get_license_key() ) && ! empty( $this->get_license_server_url() );
	}

	/**
	 * Get cached license data or fetch from server.
	 *
	 * @param bool $force_refresh Force refresh from server.
	 * @return array License data or empty array.
	 */
	public function get_license_data( $force_refresh = false ) {
		if ( ! $this->has_license() ) {
			return array();
		}

		// Check memory cache first.
		if ( null !== $this->license_data && ! $force_refresh ) {
			return $this->license_data;
		}

		// Check transient cache.
		if ( ! $force_refresh ) {
			$cached = get_transient( self::TRANSIENT_LICENSE_CACHE );
			if ( false !== $cached ) {
				$this->license_data = $cached;
				return $cached;
			}
		}

		// Fetch from server.
		$response = $this->validate_license();

		if ( is_array( $response ) && ! empty( $response['success'] ) ) {
			$this->license_data = $response;
			set_transient( self::TRANSIENT_LICENSE_CACHE, $response, self::CACHE_DURATION );
		}

		return is_array( $response ) ? $response : array();
	}

	/**
	 * Get the REST API URL for the license server.
	 *
	 * @param string $endpoint REST API endpoint path.
	 * @return string Full URL for the API endpoint.
	 */
	private function get_api_url( $endpoint ) {
		$server_url = $this->get_license_server_url();
		return $server_url . 'wp-json/ggm-license/v1/' . $endpoint;
	}

	/**
	 * Check if current site is the license server itself.
	 *
	 * @return bool True if this site is the license server.
	 */
	public function is_license_server() {
		$server_url = trailingslashit( strtolower( $this->get_license_server_url() ) );
		$site_url   = $this->get_site_url();

		// Compare normalized URLs.
		return $server_url === $site_url;
	}

	/**
	 * Validate license with server.
	 *
	 * @return array Response data.
	 */
	public function validate_license() {
		$server_url  = $this->get_license_server_url();
		$license_key = $this->get_license_key();

		if ( empty( $server_url ) || empty( $license_key ) ) {
			return array(
				'success' => false,
				'error'   => 'not_configured',
				'message' => 'License not configured.',
			);
		}

		// Skip remote validation if this site IS the license server.
		// This prevents a deadlock where the site tries to call itself.
		if ( $this->is_license_server() ) {
			return array(
				'success'      => true,
				'message'      => 'License server - validation skipped.',
				'plan_tier'    => 'unlimited',
				'widget_limit' => 0, // 0 = unlimited
				'expires_at'   => null,
				'is_server'    => true,
			);
		}

		$response = wp_remote_post(
			$this->get_api_url( 'validate' ),
			array(
				'timeout' => 15,
				'body'    => array(
					'license_key' => $license_key,
					'site_url'    => $this->get_site_url(),
				),
			)
		);

		if ( is_wp_error( $response ) ) {
			return array(
				'success' => false,
				'error'   => 'connection_error',
				'message' => $response->get_error_message(),
			);
		}

		$body        = wp_remote_retrieve_body( $response );
		$status_code = wp_remote_retrieve_response_code( $response );
		$data        = json_decode( $body, true );

		if ( ! is_array( $data ) ) {
			// Include more debug info for troubleshooting.
			return array(
				'success' => false,
				'error'   => 'invalid_response',
				'message' => 'Invalid response from license server. HTTP ' . $status_code,
			);
		}

		return $data;
	}

	/**
	 * Deactivate license for this site.
	 *
	 * @return array Response data.
	 */
	public function deactivate_license() {
		$server_url  = $this->get_license_server_url();
		$license_key = $this->get_license_key();

		if ( empty( $server_url ) || empty( $license_key ) ) {
			return array(
				'success' => false,
				'error'   => 'not_configured',
				'message' => 'License not configured.',
			);
		}

		// Skip remote call if this site IS the license server.
		if ( $this->is_license_server() ) {
			$this->clear_cache();
			return array(
				'success' => true,
				'message' => 'License server - deactivation skipped.',
			);
		}

		$response = wp_remote_post(
			$this->get_api_url( 'deactivate' ),
			array(
				'timeout' => 15,
				'body'    => array(
					'license_key' => $license_key,
					'site_url'    => $this->get_site_url(),
				),
			)
		);

		if ( is_wp_error( $response ) ) {
			return array(
				'success' => false,
				'error'   => 'connection_error',
				'message' => $response->get_error_message(),
			);
		}

		// Clear cached data.
		$this->clear_cache();

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

	/**
	 * Save license settings.
	 *
	 * @param string $license_key License key.
	 * @return array Validation response.
	 */
	public function save_license( $license_key ) {
		// Clear existing cache before saving new license.
		$this->clear_cache();

		update_option(
			self::OPTION_LICENSE,
			array(
				'license_key' => sanitize_text_field( $license_key ),
			)
		);

		// Validate the new license immediately.
		return $this->get_license_data( true );
	}

	/**
	 * Clear license cache.
	 */
	public function clear_cache() {
		$this->license_data = null;
		delete_transient( self::TRANSIENT_LICENSE_CACHE );
	}

	/**
	 * Maybe validate license periodically.
	 */
	public function maybe_validate_license() {
		if ( ! $this->has_license() ) {
			return;
		}

		// Only validate once per cache duration.
		$cached = get_transient( self::TRANSIENT_LICENSE_CACHE );
		if ( false === $cached ) {
			$this->get_license_data( true );
		}
	}

	/**
	 * Check if license is valid and active.
	 *
	 * @return bool
	 */
	public function is_license_valid() {
		$data = $this->get_license_data();
		return ! empty( $data['success'] );
	}

	/**
	 * Get the current plan tier.
	 *
	 * @return string Plan tier or empty string.
	 */
	public function get_plan_tier() {
		$data = $this->get_license_data();
		return isset( $data['plan_tier'] ) ? $data['plan_tier'] : '';
	}

	/**
	 * Get the widget limit for current license.
	 *
	 * @return int Widget limit (0 = unlimited).
	 */
	public function get_widget_limit() {
		$data = $this->get_license_data();
		return isset( $data['widget_limit'] ) ? (int) $data['widget_limit'] : 0;
	}

	/**
	 * Get license expiration date.
	 *
	 * @return string|null Expiration date or null.
	 */
	public function get_expiration_date() {
		$data = $this->get_license_data();
		return isset( $data['expires_at'] ) ? $data['expires_at'] : null;
	}

	/**
	 * Get list of activated premium widgets.
	 *
	 * @return array Widget slugs.
	 */
	public function get_activated_widgets() {
		return get_option( self::OPTION_ACTIVATED_WIDGETS, array() );
	}

	/**
	 * Activate a premium widget.
	 *
	 * @param string $widget_slug Widget slug to activate.
	 * @return array Result with success/error.
	 */
	public function activate_widget( $widget_slug ) {
		if ( ! $this->is_license_valid() ) {
			return array(
				'success' => false,
				'error'   => 'license_invalid',
				'message' => 'Valid license required to activate widgets.',
			);
		}

		$activated    = $this->get_activated_widgets();
		$widget_limit = $this->get_widget_limit();

		// Check if already activated.
		if ( in_array( $widget_slug, $activated, true ) ) {
			return array(
				'success' => true,
				'message' => 'Widget already activated.',
			);
		}

		// Check widget limit (0 = unlimited).
		if ( $widget_limit > 0 && count( $activated ) >= $widget_limit ) {
			return array(
				'success' => false,
				'error'   => 'limit_reached',
				'message' => sprintf( 'Widget limit reached (%d). Deactivate a widget or upgrade your plan.', $widget_limit ),
			);
		}

		$activated[] = $widget_slug;
		update_option( self::OPTION_ACTIVATED_WIDGETS, $activated );

		// Fire action hook for widget-specific setup (e.g., creating templates)
		do_action( 'ggm_commerce_widget_activated', $widget_slug );

		return array(
			'success' => true,
			'message' => 'Widget activated successfully.',
		);
	}

	/**
	 * Deactivate a premium widget.
	 *
	 * @param string $widget_slug Widget slug to deactivate.
	 * @return array Result with success/error.
	 */
	public function deactivate_widget( $widget_slug ) {
		$activated = $this->get_activated_widgets();
		$key       = array_search( $widget_slug, $activated, true );

		if ( false === $key ) {
			return array(
				'success' => false,
				'error'   => 'not_activated',
				'message' => 'Widget is not activated.',
			);
		}

		unset( $activated[ $key ] );
		update_option( self::OPTION_ACTIVATED_WIDGETS, array_values( $activated ) );

		return array(
			'success' => true,
			'message' => 'Widget deactivated successfully.',
		);
	}

	/**
	 * Check if a specific widget is activated.
	 *
	 * @param string $widget_slug Widget slug to check.
	 * @return bool
	 */
	public function is_widget_activated( $widget_slug ) {
		// If license not valid, no widgets are activated.
		if ( ! $this->is_license_valid() ) {
			return false;
		}

		$activated = $this->get_activated_widgets();
		return in_array( $widget_slug, $activated, true );
	}

	/**
	 * Get count of remaining widget slots.
	 *
	 * @return int|string Remaining slots or 'unlimited'.
	 */
	public function get_remaining_slots() {
		$widget_limit = $this->get_widget_limit();

		if ( 0 === $widget_limit ) {
			return 'unlimited';
		}

		$activated = $this->get_activated_widgets();
		return max( 0, $widget_limit - count( $activated ) );
	}

	/**
	 * Get license status summary.
	 *
	 * @return array Status information.
	 */
	public function get_status_summary() {
		$data = $this->get_license_data();

		if ( ! $this->has_license() ) {
			return array(
				'status'      => 'not_configured',
				'message'     => 'No license configured.',
				'is_valid'    => false,
				'plan_tier'   => '',
				'widgets'     => array(
					'limit'     => 0,
					'activated' => 0,
					'remaining' => 0,
				),
				'expires_at'  => null,
			);
		}

		if ( empty( $data['success'] ) ) {
			return array(
				'status'      => isset( $data['error'] ) ? $data['error'] : 'error',
				'message'     => isset( $data['message'] ) ? $data['message'] : 'License validation failed.',
				'is_valid'    => false,
				'plan_tier'   => '',
				'widgets'     => array(
					'limit'     => 0,
					'activated' => 0,
					'remaining' => 0,
				),
				'expires_at'  => null,
			);
		}

		$activated    = $this->get_activated_widgets();
		$widget_limit = $this->get_widget_limit();

		return array(
			'status'     => 'active',
			'message'    => 'License is valid and active.',
			'is_valid'   => true,
			'plan_tier'  => $this->get_plan_tier(),
			'widgets'    => array(
				'limit'     => $widget_limit,
				'activated' => count( $activated ),
				'remaining' => $this->get_remaining_slots(),
			),
			'expires_at' => $this->get_expiration_date(),
		);
	}
}

/**
 * Helper function to get license instance.
 *
 * @return GGM_Commerce_License
 */
function ggm_commerce_license() {
	return GGM_Commerce_License::instance();
}

// Initialize license class.
ggm_commerce_license();
