<?php
/**
 * A class for getting and setting user meta-information.
 *
 * @since 3.0.0
 */

declare(strict_types=1);
namespace FeData\FastEvents\Storage;

defined( 'ABSPATH' ) || exit;

use FeData\FastEvents\Accounts\FeAccount;
use FeData\FastEvents\Utilities\JsonUtil;
use stdClass;

/**
 * A class for getting and setting user meta-information.
 */
class UserMeta {
	/**
	 * Key for the permission user metadata.
	 *
	 * @since 2.0
	 */
	private const FE_USERMETA_PERMISSIONS = 'fast_events_rest_api_permissions';
	private const FE_SAAS_CONFIG          = 'fast_events_saas_config';
	private const FE_SAAS_MERCHANT_NAME   = 'fast_events_saas_merchant_name';
	private const FE_SAAS_PROFILE_ID      = 'fast_events_saas_profile_id';

	/**
	 * Options constructor.
	 *
	 * @since 3.0.0
	 *
	 * @param Encryption $encryption Encryption class.
	 */
	public function __construct( private readonly Encryption $encryption ) {}

	/**
	 * Singletons should not be cloneable.
	 *
	 * @since 2.5.0
	 */
	private function __clone(): void {}

	/**
	 * Prevent from being unserialised.
	 *
	 * @since 2.5.0
	 */
	public function __wakeup(): void {}

	/**
	 * Get the user API permissions.
	 *
	 * @since 2.0
	 *
	 * @param int $user_id User ID.
	 * @return stdClass|null
	 */
	public function get_user_api_permissions( int $user_id ): stdClass|null {
		$result = json_decode( $this->encryption->decrypt( get_user_meta( $user_id, self::FE_USERMETA_PERMISSIONS, true ) ) );
		if ( json_last_error() !== JSON_ERROR_NONE ) { // Invalid JSON.
			return null;
		} else {
			return $result;
		}
	}

	/**
	 * Save the user API permissions.
	 *
	 * @since 1.0
	 * @since 2.5.0 Use wp_json_encode instead of serialize.
	 *
	 * @param int       $user_id User ID.
	 * @param FeAccount $account Array of plugin settings.
	 */
	public function set_user_api_permissions( int $user_id, FeAccount $account ): void {
		update_user_meta(
			$user_id,
			self::FE_USERMETA_PERMISSIONS,
			$this->encryption->encrypt( JsonUtil::fast_events_json_encode( $account ) )
		);
	}

	/**
	 * Save the merchant name for the SaaS account.
	 *
	 * @since 1.0
	 * @since 2.5.0 Use wp_json_encode instead of serialize.
	 *
	 * @param int    $user_id       User ID.
	 * @param string $merchant_name The name of the merchant.
	 */
	public function set_saas_merchant_name( int $user_id, string $merchant_name ): void {
		update_user_meta(
			$user_id,
			self::FE_SAAS_MERCHANT_NAME,
			$this->encryption->encrypt( $merchant_name )
		);
	}

	/**
	 * Get the SaaS merchant name.
	 *
	 * @since 2.0
	 *
	 * @param int $user_id User ID.
	 * @return string|null
	 */
	public function get_saas_merchant_name( int $user_id ): string|null {
		$result = $this->encryption->decrypt( get_user_meta( $user_id, self::FE_SAAS_MERCHANT_NAME, true ) );
		if ( empty( $result ) ) { // Invalid JSON.
			return null;
		} else {
			return $result;
		}
	}

	/**
	 * Delete the SaaS merchant name.
	 *
	 * @since 2.0
	 *
	 * @param int $user_id User ID.
	 */
	public function delete_saas_merchant_name( int $user_id ): void {
		delete_user_meta( $user_id, self::FE_SAAS_MERCHANT_NAME );
	}

	/**
	 * Save the profile ID for the SaaS account.
	 *
	 * @since 1.0
	 * @since 2.5.0 Use wp_json_encode instead of serialize.
	 *
	 * @param int    $user_id    User ID.
	 * @param string $profile_id The name of the merchant.
	 */
	public function set_saas_profile_id( int $user_id, string $profile_id ): void {
		update_user_meta(
			$user_id,
			self::FE_SAAS_PROFILE_ID,
			$this->encryption->encrypt( $profile_id )
		);
	}

	/**
	 * Get the SaaS profile ID.
	 *
	 * @since 2.0
	 *
	 * @param int $user_id User ID.
	 * @return string|null
	 */
	public function get_saas_profile_id( int $user_id ): string|null {
		$result = $this->encryption->decrypt( get_user_meta( $user_id, self::FE_SAAS_PROFILE_ID, true ) );
		if ( empty( $result ) ) { // Invalid JSON.
			return null;
		} else {
			return $result;
		}
	}

	/**
	 * Delete the SaaS profile ID.
	 *
	 * @since 2.0
	 *
	 * @param int $user_id User ID.
	 */
	public function delete_saas_profile_id( int $user_id ): void {
		delete_user_meta( $user_id, self::FE_SAAS_PROFILE_ID );
	}

	/**
	 * Save the SaaS configuration (refresh_token, access_token, ...).
	 *
	 * @since 1.0
	 * @since 2.5.0 Use wp_json_encode instead of serialize.
	 *
	 * @param int   $user_id User ID.
	 * @param array $config  The SaaS configuration structure.
	 */
	public function set_saas_config( int $user_id, array $config ): void {
		update_user_meta(
			$user_id,
			self::FE_SAAS_CONFIG,
			$this->encryption->encrypt( JsonUtil::fast_events_json_encode( $config ) )
		);
	}

	/**
	 * Get the SaaS configuration (refresh_token, access_token, ...).
	 *
	 * @since 2.0
	 *
	 * @param int $user_id User ID.
	 * @return stdClass|null
	 */
	public function get_saas_config( int $user_id ): stdClass|null {
		$result = json_decode( $this->encryption->decrypt( get_user_meta( $user_id, self::FE_SAAS_CONFIG, true ) ) );
		if ( json_last_error() !== JSON_ERROR_NONE ) { // Invalid JSON.
			return null;
		} else {
			return $result;
		}
	}

	/**
	 * Delete the SaaS configuration (refresh_token, access_token, ...).
	 *
	 * @since 2.0
	 *
	 * @param int $user_id User ID.
	 */
	public function delete_saas_config( int $user_id ): void {
		delete_user_meta( $user_id, self::FE_SAAS_CONFIG );
	}
}
