<?php
/**
 * RSM Licensing Server client.
 *
 * @package Rsmspark_Content_Widgets
 */

defined( 'ABSPATH' ) || exit;

/**
 * Rsmspark_Content_Widgets_License
 */
class Rsmspark_Content_Widgets_License {

	const OPTION_LICENSE_DATA = 'rsmspark_content_widgets_license_data';
	const OPTION_VALIDATED_AT = 'rsmspark_content_widgets_license_validated_at';
	const OPTION_LAST_RESULT  = 'rsmspark_content_widgets_license_last_result';

	const API_NAMESPACE    = 'rsm-licensing/v1';
	const VALIDATE_CACHE_H = 24;

	/**
	 * @return string
	 */
	public static function get_server_url() {
		$settings = Rsmspark_Content_Widgets_Settings::get();
		$url      = untrailingslashit( esc_url_raw( (string) ( $settings['license_server_url'] ?? '' ) ) );
		if ( '' === $url && class_exists( 'Rsmspark_License_Client', false ) ) {
			$url = Rsmspark_License_Client::get_suite_server_url();
		}
		return $url;
	}

	/**
	 * @return string
	 */
	public static function get_license_key() {
		$settings = Rsmspark_Content_Widgets_Settings::get();
		return strtoupper( preg_replace( '/[^A-Z0-9\-]/', '', (string) ( $settings['license_key'] ?? '' ) ) );
	}

	/**
	 * @return string
	 */
	public static function get_plugin_slug() {
		return RSMSPARK_CONTENT_WIDGETS_SLUG;
	}

	/**
	 * @return string
	 */
	public static function get_site_url() {
		return untrailingslashit( site_url() );
	}

	/**
	 * @return string
	 */
	public static function get_api_base() {
		$server = self::get_server_url();
		if ( '' === $server ) {
			return '';
		}
		return trailingslashit( $server ) . 'wp-json/' . self::API_NAMESPACE;
	}

	/**
	 * @param string|null $license_key Optional key override.
	 * @return array<string, mixed>
	 */
	public static function activate_license( $license_key = null ) {
		$license_key = null !== $license_key ? self::sanitize_key( $license_key ) : self::get_license_key();
		if ( '' === $license_key ) {
			return self::error( 'missing_license_key', __( 'Enter a license key first.', 'rsm-content-widgets' ) );
		}

		self::persist_license_key( $license_key );

		$response = self::request(
			'activate',
			array(
				'license_key'    => $license_key,
				'site_url'       => self::get_site_url(),
				'plugin_slug'    => self::get_plugin_slug(),
				'plugin_version' => RSMSPARK_CONTENT_WIDGETS_VERSION,
			)
		);

		if ( ! empty( $response['success'] ) && ! empty( $response['license'] ) ) {
			self::store_license_data( $response['license'] );
			do_action( 'rsmspark_content_widgets_license_activated', $response['license'] );
		}

		self::store_last_result( 'activate', $response );
		return $response;
	}

	/**
	 * @param bool $force Skip cache.
	 * @return array<string, mixed>
	 */
	public static function validate_license( $force = false ) {
		if ( ! $force && self::has_fresh_cache() ) {
			return array(
				'success' => true,
				'valid'   => self::is_premium(),
				'license' => self::get_license_data(),
				'cached'  => true,
			);
		}

		$license_key = self::get_license_key();
		if ( '' === $license_key ) {
			return self::error( 'missing_license_key', __( 'No license key stored on this site.', 'rsm-content-widgets' ) );
		}

		$response = self::request(
			'validate',
			array(
				'license_key' => $license_key,
				'site_url'    => self::get_site_url(),
				'plugin_slug' => self::get_plugin_slug(),
			)
		);

		if ( ! empty( $response['success'] ) && ! empty( $response['license'] ) ) {
			self::store_license_data( $response['license'] );
		} elseif ( ! empty( $response['success'] ) && empty( $response['valid'] ) ) {
			self::clear_license_cache();
		} elseif ( empty( $response['success'] ) ) {
			self::clear_license_cache();
		}

		self::store_last_result( 'validate', $response );
		return $response;
	}

	/**
	 * @return array<string, mixed>
	 */
	public static function deactivate_license() {
		$license_key = self::get_license_key();
		if ( '' === $license_key ) {
			return self::error( 'missing_license_key', __( 'No license key stored on this site.', 'rsm-content-widgets' ) );
		}

		$response = self::request(
			'deactivate',
			array(
				'license_key' => $license_key,
				'site_url'    => self::get_site_url(),
				'plugin_slug' => self::get_plugin_slug(),
			)
		);

		if ( ! empty( $response['success'] ) ) {
			self::clear_license_cache();
			do_action( 'rsmspark_content_widgets_license_deactivated' );
		}

		self::store_last_result( 'deactivate', $response );
		return $response;
	}

	/**
	 * @return bool
	 */
	public static function is_premium() {
		return false;
	}

	/**
	 * @param string $feature Feature flag key.
	 * @return bool
	 */
	public static function has_feature( $feature ) {
		unset( $feature );
		return false;
	}

	/**
	 * @param string $registry_id Widget registry id.
	 * @return bool
	 */
	public static function can_use_widget( $registry_id ) {
		if ( ! Rsmspark_Content_Widgets_Registry::is_pro_widget( $registry_id ) ) {
			return true;
		}
		return self::has_feature( 'base_pro' );
	}

	/**
	 * @return array<string, mixed>
	 */
	public static function get_license_data() {
		$data = get_option( self::OPTION_LICENSE_DATA, array() );
		return is_array( $data ) ? $data : array();
	}

	/**
	 * @return array<string, mixed>|null
	 */
	public static function get_last_result() {
		$data = get_option( self::OPTION_LAST_RESULT, null );
		return is_array( $data ) ? $data : null;
	}

	/**
	 * @return string
	 */
	public static function get_status_label() {
		if ( self::is_premium() ) {
			$data = class_exists( 'Rsmspark_License_Client', false )
				? Rsmspark_License_Client::get_license_data_for_plugin( self::get_plugin_slug() )
				: self::get_license_data();
			if ( empty( $data ) ) {
				$data = self::get_license_data();
			}
			$plan = sanitize_key( (string) ( $data['plan'] ?? 'pro' ) );
			return 'pro' === $plan ? __( 'Pro (Active)', 'rsm-content-widgets' ) : ucfirst( $plan );
		}

		$data = self::get_license_data();
		if ( ! empty( $data ) ) {
			$status = sanitize_key( (string) ( $data['effective_status'] ?? $data['status'] ?? '' ) );
			if ( 'expired' === $status ) {
				return __( 'Expired', 'rsm-content-widgets' );
			}
			if ( 'revoked' === $status ) {
				return __( 'Revoked', 'rsm-content-widgets' );
			}
		}

		return __( 'Free', 'rsm-content-widgets' );
	}

	/**
	 * @return string[]
	 */
	public static function enabled_feature_labels() {
		$labels = array( __( 'Core widgets', 'rsm-content-widgets' ) );
		if ( self::has_feature( 'base_pro' ) ) {
			$labels[] = __( 'Pro widgets (Dynamic Grid, Carousel, Pricing, Testimonials)', 'rsm-content-widgets' );
		}
		if ( self::has_feature( 'dynamic_grid' ) ) {
			$labels[] = __( 'Dynamic Grid — advanced query, filters, load more', 'rsm-content-widgets' );
		}
		if ( self::has_feature( 'advanced_animations' ) ) {
			$labels[] = __( 'Advanced Carousel — sync and autoplay', 'rsm-content-widgets' );
		}
		return $labels;
	}

	/**
	 * @return void
	 */
	public static function clear_license_cache() {
		delete_option( self::OPTION_LICENSE_DATA );
		delete_option( self::OPTION_VALIDATED_AT );
	}

	/**
	 * @param string $license_key License key.
	 * @return void
	 */
	private static function persist_license_key( $license_key ) {
		$settings                = Rsmspark_Content_Widgets_Settings::get();
		$settings['license_key'] = self::sanitize_key( $license_key );
		Rsmspark_Content_Widgets_Settings::save( $settings );
	}

	/**
	 * @param string               $endpoint Endpoint.
	 * @param array<string, mixed> $body     Body.
	 * @return array<string, mixed>
	 */
	private static function request( $endpoint, array $body ) {
		$base = self::get_api_base();
		if ( '' === $base ) {
			return self::error( 'missing_server', __( 'Set the licensing server URL first.', 'rsm-content-widgets' ) );
		}

		$url  = trailingslashit( $base ) . sanitize_key( $endpoint );
		$resp = wp_remote_post(
			$url,
			array(
				'timeout' => 20,
				'headers' => array( 'Content-Type' => 'application/json' ),
				'body'    => wp_json_encode( $body ),
			)
		);

		if ( is_wp_error( $resp ) ) {
			return self::error( 'http_error', $resp->get_error_message() );
		}

		$code = (int) wp_remote_retrieve_response_code( $resp );
		$data = json_decode( (string) wp_remote_retrieve_body( $resp ), true );
		if ( ! is_array( $data ) ) {
			return self::error( 'invalid_response', sprintf( 'HTTP %d', $code ) );
		}

		$data['http_code'] = $code;
		return $data;
	}

	/**
	 * @param array<string, mixed> $license License payload.
	 * @return void
	 */
	private static function store_license_data( array $license ) {
		update_option( self::OPTION_LICENSE_DATA, $license, false );
		update_option( self::OPTION_VALIDATED_AT, time(), false );
	}

	/**
	 * @param string               $action Action.
	 * @param array<string, mixed> $result Result.
	 * @return void
	 */
	private static function store_last_result( $action, array $result ) {
		update_option(
			self::OPTION_LAST_RESULT,
			array(
				'action' => sanitize_key( $action ),
				'time'   => gmdate( 'c' ),
				'result' => $result,
			),
			false
		);
	}

	/**
	 * @return bool
	 */
	private static function has_fresh_cache() {
		$validated_at = (int) get_option( self::OPTION_VALIDATED_AT, 0 );
		if ( $validated_at <= 0 || empty( self::get_license_data() ) ) {
			return false;
		}
		return ( time() - $validated_at ) < ( self::VALIDATE_CACHE_H * HOUR_IN_SECONDS );
	}

	/**
	 * @param string $license_key License key.
	 * @return string
	 */
	private static function sanitize_key( $license_key ) {
		return strtoupper( preg_replace( '/[^A-Z0-9\-]/', '', (string) $license_key ) );
	}

	/**
	 * @param string $code    Error code.
	 * @param string $message Message.
	 * @return array<string, mixed>
	 */
	private static function error( $code, $message ) {
		return array(
			'success' => false,
			'error'   => array(
				'code'    => sanitize_key( $code ),
				'message' => $message,
			),
		);
	}
}
