<?php
/**
 * Restricts post/page content visibility to selected roles.
 *
 * @package wpss-ultimate-user-management
 */

namespace WpssUserManager\Admin;

/** Prevent direct access */
if ( ! defined( 'ABSPATH' ) ) {
	header( 'HTTP/1.0 403 Forbidden' );
	exit;
}

/**
 * Class WPSSContentAccess
 *
 * @since 1.1.0
 */
class WPSSContentAccess {
	/**
	 * Instance of this class.
	 *
	 * @var object|null
	 * @since 1.1.0
	 */
	protected static ?object $instance = null;

	/**
	 * Post meta key that stores the roles allowed to view a post's content.
	 *
	 * @var string
	 * @since 1.1.0
	 */
	public static string $wpss_post_type_access_key = 'wpss_content_allowed_roles';

	/**
	 * Register the metabox, save, and content-filtering hooks.
	 *
	 * @since 1.1.0
	 */
	public function __construct() {
		add_action( 'add_meta_boxes', [ $this, 'content_access_metabox' ] );
		add_action( 'save_post', [ $this, 'content_access_save_metadata' ] );
		add_filter( 'the_content', [ $this, 'limit_role_content_access' ] );
	}

	/**
	 * Get class instance
	 *
	 * @return object
	 * @since 1.1.0
	 */
	public static function instance(): object {
		if ( is_null( self::$instance ) ) {
			self::$instance = new self();
		}

		return self::$instance;
	}

	/**
	 * Replace the post content with the access-denied message when the current user's role isn't allowed.
	 *
	 * @param string $content Post content, as filtered by 'the_content'.
	 * @return string
	 * @since 1.1.0
	 */
	public function limit_role_content_access( string $content ): string {
		$get_allowed_roles = get_post_meta( get_the_ID(), self::$wpss_post_type_access_key, true );
		$is_allowed        = false;
		$cpt_protected     = WPSSPluginHelper::get_option( 'wpss_cpt_access_control' );
		if ( ! empty( $cpt_protected ) ) {
			$cpt_protected = json_decode( $cpt_protected, true );
		} else {
			$cpt_protected = [];
		}
		if ( ! in_array( get_post_type(), $cpt_protected, true ) ) {
			return $content;
		}
		if ( $get_allowed_roles ) {
			$get_allowed_roles = json_decode( $get_allowed_roles, true );
			foreach ( $get_allowed_roles as $allowed_role ) {
				if ( current_user_can( $allowed_role ) ) {
					$is_allowed = true;
					break;
				}
			}

			if ( ! $is_allowed ) {
				$message = WPSSPluginHelper::get_option( 'wpss_cpt_access_message' );
				if ( empty( $message ) ) {
					$message = __( 'No permission to view this content.', 'wpss-ultimate-user-management' );
				}
				$content = $message;
			}
		}
		return $content;
	}

	/**
	 * Define metabox
	 *
	 * @return void
	 * @since 1.1.0
	 */
	public function content_access_metabox(): void {
		$get_access_cpt = WPSSPluginHelper::get_option( 'wpss_cpt_access_control' );
		if ( ! empty( $get_access_cpt ) ) {
			$get_access_cpt = json_decode( $get_access_cpt, true );
		} else {
			$get_access_cpt = 'nullcpt_not_set';
		}
		add_meta_box(
			'wpss_content_access_metabox',
			__( 'Who can access: ', 'wpss-ultimate-user-management' ),
			[ $this, 'content_access_metabox_cb' ],
			$get_access_cpt,
			'side',
			'high',
		);
	}

	/**
	 * Render metabox content
	 *
	 * @return void
	 * @since 1.1.0
	 */
	public function content_access_metabox_cb(): void {
		$template = [ 'template' => 'content/post-type-access-metabox' ];
		WPSSAdminFrontend::render( $template );
	}

	/**
	 * Save content on post meta.
	 *
	 * @param int $post_id Post being saved.
	 * @return void
	 * @since 1.1.0
	 */
	public function content_access_save_metadata( int $post_id ): void {
		if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
			return;
		}
		$cpt_with_access_rules = WPSSPluginHelper::get_option( 'wpss_cpt_access_control' );
		if ( $cpt_with_access_rules ) {
			$cpt_with_access_rules = json_decode( $cpt_with_access_rules, true );
		} else {
			$cpt_with_access_rules = [];
		}
		$wpss_get_post_type = get_post_type( $post_id );
		if ( in_array( $wpss_get_post_type, $cpt_with_access_rules, true ) ) {
			$nonce            = wp_create_nonce( WPSSUserRolesCapsManager::nonce() );
			$post_role_access = RoleCraftRequest::post( self::$wpss_post_type_access_key, true, $nonce ) ?? false;
			if ( $post_role_access ) {
				update_post_meta( $post_id, self::$wpss_post_type_access_key, $post_role_access );
			} else {
				delete_post_meta( $post_id, self::$wpss_post_type_access_key );
			}
		}
	}
}
