<?php
/**
 * Product Visibility class file.
 *
 * @package WholesaleNode_For_WooCommerce
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Restricts product visibility by user role.
 */
class WOOWSNFree_Product_Visibility {

	private static $_instance = null;

	/**
	 * @return self
	 */
	public static function instance() {
		if ( is_null( self::$_instance ) ) {
			self::$_instance = new self();
		}
		return self::$_instance;
	}

	private function __construct() {
		add_filter( 'woocommerce_product_is_visible', array( $this, 'filter_visibility' ), 20, 2 );
		add_action( 'template_redirect',              array( $this, 'check_single_access' ) );
		add_filter( 'woocommerce_add_to_cart_validation', array( $this, 'block_cart' ), 10, 2 );

		add_action( 'add_meta_boxes',    array( $this, 'register_meta_box' ) );
		add_action( 'save_post_product', array( $this, 'save_meta_box' ), 20 );
	}

	/**
	 * Determine whether the current user can view a product.
	 *
	 * @param int $product_id Product ID.
	 * @return bool
	 */
	public function user_can_view( $product_id ) {
		$visibility = get_post_meta( $product_id, '_woowsn_product_visibility_role', true );

		if ( ! $visibility || $visibility === 'everyone' ) {
			return true;
		}

		$user_id = get_current_user_id();

		if ( $visibility === 'logged_in_only' ) {
			return (bool) $user_id;
		}

		if ( $visibility === 'wholesaler_only' ) {
			if ( ! $user_id ) {
				return false;
			}
			$user = get_userdata( $user_id );
			return $user && in_array( 'wholesaler', (array) $user->roles, true );
		}

		return true;
	}

	/**
	 * Filter WooCommerce product visibility in shop / archive loops.
	 *
	 * @param bool $visible    Current visibility.
	 * @param int  $product_id Product ID.
	 * @return bool
	 */
	public function filter_visibility( $visible, $product_id ) {
		if ( ! $visible ) {
			return false;
		}
		return $this->user_can_view( $product_id );
	}

	/**
	 * Redirect from single product page when access is restricted.
	 */
	public function check_single_access() {
		if ( ! is_product() ) {
			return;
		}
		global $post;
		if ( $post && ! $this->user_can_view( $post->ID ) ) {
			wp_safe_redirect( wc_get_page_permalink( 'shop' ) ?: home_url() );
			exit;
		}
	}

	/**
	 * Block add-to-cart for restricted products.
	 *
	 * @param bool $passed     Passed validation.
	 * @param int  $product_id Product ID.
	 * @return bool
	 */
	public function block_cart( $passed, $product_id ) {
		if ( ! $this->user_can_view( $product_id ) ) {
			wc_add_notice( __( 'You do not have access to this product.', 'wholesalenode-for-woocommerce' ), 'error' );
			return false;
		}
		return $passed;
	}

	/**
	 * Register the product meta box.
	 */
	public function register_meta_box() {
		add_meta_box(
			'woowsn_free_visibility',
			__( 'B2B Product Visibility', 'wholesalenode-for-woocommerce' ),
			array( $this, 'render_meta_box' ),
			'product',
			'side',
			'default'
		);
	}

	/**
	 * Render the product visibility meta box.
	 *
	 * @param WP_Post $post Post object.
	 */
	public function render_meta_box( $post ) {
		$value = get_post_meta( $post->ID, '_woowsn_product_visibility_role', true );
		wp_nonce_field( 'woowsn_free_visibility_product', 'woowsn_free_visibility_nonce' );
		?>
		<p><label for="woowsn_free_visibility"><?php esc_html_e( 'Visible to:', 'wholesalenode-for-woocommerce' ); ?></label></p>
		<select name="woowsn_free_visibility" id="woowsn_free_visibility" class="widefat">
			<option value=""              <?php selected( $value, '' ); ?>><?php esc_html_e( 'Everyone (default)', 'wholesalenode-for-woocommerce' ); ?></option>
			<option value="logged_in_only" <?php selected( $value, 'logged_in_only' ); ?>><?php esc_html_e( 'Logged-in users only', 'wholesalenode-for-woocommerce' ); ?></option>
			<option value="wholesaler_only" <?php selected( $value, 'wholesaler_only' ); ?>><?php esc_html_e( 'Wholesalers only', 'wholesalenode-for-woocommerce' ); ?></option>
		</select>
		<p class="description"><?php esc_html_e( 'Guests / non-matching users will be redirected away from this product.', 'wholesalenode-for-woocommerce' ); ?></p>
		<?php
	}

	/**
	 * Save the product visibility meta box value.
	 *
	 * @param int $post_id Post ID.
	 */
	public function save_meta_box( $post_id ) {
		if (
			wp_is_post_autosave( $post_id ) ||
			wp_is_post_revision( $post_id ) ||
			get_post_type( $post_id ) !== 'product'
		) {
			return;
		}

		if (
			! isset( $_POST['woowsn_free_visibility_nonce'] ) ||
			! wp_verify_nonce(
				sanitize_text_field( wp_unslash( $_POST['woowsn_free_visibility_nonce'] ) ),
				'woowsn_free_visibility_product'
			)
		) {
			return;
		}

		if ( ! current_user_can( 'edit_post', $post_id ) ) {
			return;
		}

		$allowed = array( '', 'logged_in_only', 'wholesaler_only' );
		$raw     = isset( $_POST['woowsn_free_visibility'] ) ? sanitize_text_field( wp_unslash( $_POST['woowsn_free_visibility'] ) ) : '';
		$value   = in_array( $raw, $allowed, true ) ? $raw : '';

		update_post_meta( $post_id, '_woowsn_product_visibility_role', $value );
	}
}
