<?php
/**
 * Custom App utility class file.
 *
 * @since 1.0.2
 * @package sureforms-pro
 */

namespace SRFM_Pro\Inc\Business\Custom_App;

use SRFM\Inc\Helper;

// Exit if accessed directly.
defined( 'ABSPATH' ) || exit;

/**
 * Utility and helper methods for the custom app feature.
 *
 * @since 1.0.2
 */
class Utils {
	/**
	 * Key for the rest api route.
	 *
	 * @since 1.0.2
	 */
	public const REST_ROUTE = 'custom-app-webhook';

	/**
	 * Session ID key.
	 *
	 * @since 1.0.2
	 */
	public const SESSION_ID_KEY = 'srfm_pro_custom_app_user_session_id';

	/**
	 * Current user Session ID cache.
	 *
	 * @var string
	 * @since 1.0.2
	 */
	public static $session_id = '';

	/**
	 * Returns current user session id.
	 *
	 * @since 1.0.2
	 * @return string
	 */
	public static function get_user_session_id() {
		if ( self::$session_id ) {

			/**
			 * Return the cached session id
			 * so we don't regenerate session id if it is in loop.
			 */
			return self::$session_id;
		}

		self::$session_id = isset( $_COOKIE[ self::SESSION_ID_KEY ] ) ? sanitize_text_field( wp_unslash( $_COOKIE[ self::SESSION_ID_KEY ] ) ) : '';

		// Generate session id if we don't have one.
		if ( ! self::$session_id ) {
			self::$session_id = md5( wp_generate_uuid4() . microtime( true ) );

			if ( ! headers_sent() ) {
				// Set session cookie. Expires when browser or tab is closed.
				setcookie( self::SESSION_ID_KEY, self::$session_id, 0, '/' );
			}
		}

		return self::$session_id;
	}

	/**
	 * Check if the custom app is enabled for the given form ID.
	 *
	 * @param int $form_id The ID of the form post.
	 * @return bool True if the custom app is enabled; false otherwise.
	 *
	 * @since 1.9.0
	 */
	public static function is_custom_app_enabled( $form_id ) {
		if ( ! $form_id ) {
			return false;
		}

		// Get the form confirmation meta.
		$form_confirmation = get_post_meta( $form_id, '_srfm_form_confirmation', true );

		if ( empty( $form_confirmation ) || ! is_array( $form_confirmation ) ) {
			return false;
		}

		$first_confirmation = $form_confirmation[0] ?? [];

		$form_confirmation = Helper::get_array_value( $first_confirmation );

		return isset( $form_confirmation['confirmation_type'] )
			&& 'suretriggers_below_form' === $form_confirmation['confirmation_type'];
	}

	/**
	 * Returns response callback url.
	 *
	 * @param string $session_id Current user session id.
	 * @param int    $form_id Form ID.
	 * @since 1.0.2
	 * @return string Response URL.
	 */
	public static function get_response_url( $session_id, $form_id ) {
		if ( empty( $session_id ) || empty( $form_id ) ) {
			// Bail early if either of this variable is empty.
			return '';
		}

		$token = base64_encode( // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode -- It is okay to use this function here as it is our own data.
			strval(
				wp_json_encode(
					[
						'session_id' => $session_id,
						'form_id'    => absint( $form_id ),
						'nonce'      => self::create_nonce( $session_id ),
						'timestamp'  => time(),
					]
				)
			)
		);

		return add_query_arg( 'token', $token, rest_url( 'sureforms-pro/v1/' . self::REST_ROUTE ) );
	}

	/**
	 * Create and save nonce temporary according to the session id.
	 *
	 * @param string $session_id Current user session id.
	 * @since 1.0.2
	 * @return string Created nonce key.
	 */
	public static function create_nonce( $session_id ) {
		$key   = "_srfm_pro_custom_app_{$session_id}_nonce";
		$nonce = wp_create_nonce( $key );
		set_transient( $key, $nonce, DAY_IN_SECONDS );
		return $nonce;
	}

	/**
	 * Verify the nonce.
	 *
	 * @param string $nonce Created nonce.
	 * @param string $session_id Current user session id.
	 * @since 1.0.2
	 * @return bool True on success or false on failure.
	 */
	public static function verify_nonce( $nonce, $session_id ) {
		return get_transient( "_srfm_pro_custom_app_{$session_id}_nonce" ) === $nonce;
	}

	/**
	 * Saves result data temporary according to the session id.
	 *
	 * @param string       $session_id Current user session id.
	 * @param int          $form_id Form ID.
	 * @param array<mixed> $data Data to save.
	 * @since 1.0.2
	 * @return bool
	 */
	public static function set_result_transient( $session_id, $form_id, $data = [] ) {
		return set_transient( "_srfm_pro_{$session_id}_{$form_id}", $data, DAY_IN_SECONDS );
	}

	/**
	 * Returns temporary saved data.
	 *
	 * @param string $session_id Current user session id.
	 * @param int    $form_id Form Id.
	 * @since 1.0.2
	 * @return mixed Temporary data.
	 */
	public static function get_result_transient( $session_id, $form_id ) {
		return get_transient( "_srfm_pro_{$session_id}_{$form_id}" );
	}

	/**
	 * Delete temporary saved data.
	 *
	 * @param string $session_id Current user session id.
	 * @param int    $form_id Form id.
	 * @since 1.0.2
	 * @return bool
	 */
	public static function delete_result_transient( $session_id, $form_id ) {
		return delete_transient( "_srfm_pro_{$session_id}_{$form_id}" );
	}
}
