<?php
/**
 * Taxonomy View Restriction Class
 *
 * Handles frontend access control for posts based on taxonomy restrictions
 * in user subscription packs.
 *
 * @since   4.1.9
 * @package WPUF_Pro
 */

namespace WeDevs\Wpuf\Pro\Frontend;

if ( ! defined( 'ABSPATH' ) ) {
    exit; // Exit if accessed directly
}

/**
 * Taxonomy View Restriction Class
 *
 * @since 4.1.9
 */
class Taxonomy_View_Restriction {

    /**
     * Constructor
     *
     * @since 4.1.9
     */
    public function __construct() {
        // Check if Post View Categories feature is available
        if ( ! wpuf_is_post_view_categories_available() ) {
            return;
        }

        add_filter( 'the_content', [ $this, 'check_taxonomy_view_access' ], 20 );
        add_action( 'wp_head', [ $this, 'add_noindex_for_restricted_posts' ] );
    }

    /**
     * Check if user can view post based on taxonomy restrictions
     *
     * @since 4.1.9
     *
     * @param int $post_id The post ID to check
     *
     * @return bool True if user can view, false otherwise
     */
    public function user_can_view_post_by_taxonomy( $post_id ) {
        // Admin users always have access
        if ( current_user_can( 'administrator' ) ) {
            return true;
        }
        // Check if user is logged in
        if ( ! is_user_logged_in() ) {
            return false;
        }
        $current_user_id = get_current_user_id();
        $user_pack       = get_user_meta( $current_user_id, '_wpuf_subscription_pack', true );
        // If user has no subscription pack, deny access
        if ( ! $user_pack || $user_pack === 'Cancel' || $user_pack === 'cancel' || ! isset( $user_pack['pack_id'] ) ) {
            return false;
        }
        $pack_id               = $user_pack['pack_id'];
        $view_allowed_term_ids = get_post_meta( $pack_id, '_sub_view_allowed_term_ids', true );
        // If no view restrictions are set, allow all posts
        if ( empty( $view_allowed_term_ids ) || ! is_array( $view_allowed_term_ids ) ) {
            return true;
        }
        // Get post taxonomy terms
        $post_terms = $this->get_post_taxonomy_terms( $post_id );
        // If post has no taxonomy terms, deny access (conservative approach)
        if ( empty( $post_terms ) ) {
            return false;
        }
        // Check if there's any intersection between post terms and allowed terms
        $intersection = array_intersect( $post_terms, $view_allowed_term_ids );

        return ! empty( $intersection );
    }

    /**
     * Get all taxonomy term IDs for a post
     *
     * @since 4.1.9
     *
     * @param int $post_id The post ID
     *
     * @return array Array of term IDs
     */
    private function get_post_taxonomy_terms( $post_id ) {
        $term_ids   = [];
        $taxonomies = get_taxonomies( [ 'hierarchical' => true ], 'names' );
        foreach ( $taxonomies as $taxonomy ) {
            $terms = wp_get_post_terms( $post_id, $taxonomy, [ 'fields' => 'ids' ] );
            if ( ! is_wp_error( $terms ) && ! empty( $terms ) ) {
                $term_ids = array_merge( $term_ids, $terms );
            }
        }

        return array_unique( $term_ids );
    }

    /**
     * Check taxonomy view access and filter content accordingly
     *
     * @since 4.1.9
     *
     * @param string $content The post content
     *
     * @return string Modified content or access denied message
     */
    public function check_taxonomy_view_access( $content ) {
        global $post;
        // Only run on single post pages
        if ( ! is_single() ) {
            return $content;
        }
        if ( ! $post || ! is_object( $post ) ) {
            return $content;
        }
        // Check global meta first - if no restrictions anywhere, show content
        if ( ! $this->any_pack_has_taxonomy_restrictions() ) {
            return $content;
        }
        // Get post taxonomy terms first
        $post_terms = $this->get_post_taxonomy_terms( $post->ID );
        // If post has no taxonomy terms, show content (no restrictions apply)
        if ( empty( $post_terms ) ) {
            return $content;
        }
        // Check if this specific post has any restricted terms
        $has_restricted_terms = $this->post_has_restricted_terms( $post_terms );
        if ( ! $has_restricted_terms ) {
            return $content;
        }
        // Check if current user can access this post
        if ( ! $this->user_can_view_post_by_taxonomy( $post->ID ) ) {
            return $this->get_access_denied_message( $post->ID );
        }

        return $content;
    }

    /**
     * Get access denied message with relevant subscription packs
     *
     * @since 4.1.9
     *
     * @param int $post_id The post ID
     *
     * @return string Access denied message
     */
    private function get_access_denied_message( $post_id ) {
        $message = __( 'Access Restricted', 'wpuf-pro' );
        $message .= '<br><br>';
        $message .= __(
            'This content is restricted based on your subscription plan. Please upgrade your subscription to access this content.',
            'wpuf-pro'
        );
        // Get relevant subscription packs
        $relevant_packs = $this->get_relevant_subscription_packs( $post_id );
        if ( ! empty( $relevant_packs ) ) {
            $message .= '<br><br>';
            $message .= __( 'Available subscription plans for this content:', 'wpuf-pro' );
            $message .= '<br><br>';
            foreach ( $relevant_packs as $pack ) {
                $pack_title = get_the_title( $pack->ID );
                $message    .= sprintf(
                    '<strong>%s</strong><br>',
                    esc_html( $pack_title )
                );
            }
        } else {
            // Fallback to general subscription page
            $subscription_page = wpuf_get_option( 'subscription_page', 'wpuf_payment' );
            if ( $subscription_page ) {
                $message .= '<br><br>';
                $message .= sprintf(
                    '<a href="%s" class="wpuf-subscription-link">%s</a>',
                    esc_url( get_permalink( $subscription_page ) ),
                    __( 'View Subscription Plans', 'wpuf-pro' )
                );
            }
        }
        $message = apply_filters( 'wpuf_taxonomy_view_restriction_message', $message, $post_id );

        return '<div class="wpuf-access-restricted">' . $message . '</div>';
    }

    /**
     * Add noindex meta tag for restricted posts to prevent SEO issues
     *
     * @since 4.1.9
     */
    public function add_noindex_for_restricted_posts() {
        global $post;
        if ( ! $post || ! is_object( $post ) ) {
            return;
        }
        // Check global meta first - if no restrictions anywhere, don't add noindex
        if ( ! $this->any_pack_has_taxonomy_restrictions() ) {
            return;
        }
        // Get post taxonomy terms first
        $post_terms = $this->get_post_taxonomy_terms( $post->ID );
        // If post has no taxonomy terms, don't add noindex
        if ( empty( $post_terms ) ) {
            return;
        }
        // Check if this specific post has any restricted terms
        $has_restricted_terms = $this->post_has_restricted_terms( $post_terms );
        if ( ! $has_restricted_terms ) {
            return;
        }
        // Check if current user can't access this post
        if ( ! $this->user_can_view_post_by_taxonomy( $post->ID ) ) {
            echo '<meta name="robots" content="noindex, nofollow" />' . "\n";
        }
    }

    /**
     * Check if a subscription pack has view restrictions
     *
     * @since 4.1.9
     *
     * @param int $pack_id The subscription pack ID
     *
     * @return bool True if pack has view restrictions
     */
    public function pack_has_view_restrictions( $pack_id ) {
        $view_allowed_term_ids = get_post_meta( $pack_id, '_sub_view_allowed_term_ids', true );

        return ! empty( $view_allowed_term_ids ) && is_array( $view_allowed_term_ids );
    }

    /**
     * Get allowed terms for a subscription pack
     *
     * @since 4.1.9
     *
     * @param int $pack_id The subscription pack ID
     *
     * @return array Array of allowed term IDs
     */
    public function get_pack_view_allowed_terms( $pack_id ) {
        $view_allowed_term_ids = get_post_meta( $pack_id, '_sub_view_allowed_term_ids', true );

        return is_array( $view_allowed_term_ids ) ? $view_allowed_term_ids : [];
    }

    /**
     * Check if any subscription pack has taxonomy view restrictions
     *
     * @since 4.1.9
     *
     * @return bool True if any pack has restrictions
     */
    public function any_pack_has_taxonomy_restrictions() {
        $enabled = get_option( 'wpuf_taxonomy_view_restrictions_enabled', 'no' );

        return $enabled === 'yes';
    }

    /**
     * Get relevant subscription packs for a post
     *
     * @since 4.1.9
     *
     * @param int $post_id The post ID
     *
     * @return array Array of subscription pack objects
     */
    public function get_relevant_subscription_packs( $post_id ) {
        $post_terms = $this->get_post_taxonomy_terms( $post_id );
        if ( empty( $post_terms ) ) {
            return [];
        }
        $relevant_packs = [];
        $all_packs      = get_posts(
            [
                'post_type'      => 'wpuf_subscription',
                'posts_per_page' => - 1,
                'post_status'    => 'publish',
            ]
        );
        foreach ( $all_packs as $pack ) {
            $allowed_terms = get_post_meta( $pack->ID, '_sub_view_allowed_term_ids', true );
            if ( ! empty( $allowed_terms ) && is_array( $allowed_terms ) ) {
                $intersection = array_intersect( $post_terms, $allowed_terms );
                if ( ! empty( $intersection ) ) {
                    $relevant_packs[] = $pack;
                }
            }
        }

        return $relevant_packs;
    }

    /**
     * Check if a post has any terms that are restricted by any subscription pack
     *
     * @since 4.1.9
     *
     * @param array $post_terms Array of term IDs
     *
     * @return bool True if post has restricted terms
     */
    private function post_has_restricted_terms( $post_terms ) {
        $all_packs = get_posts(
            [
                'post_type'      => 'wpuf_subscription',
                'posts_per_page' => - 1,
                'post_status'    => 'publish',
            ]
        );
        foreach ( $all_packs as $pack ) {
            $allowed_terms = get_post_meta( $pack->ID, '_sub_view_allowed_term_ids', true );
            if ( ! empty( $allowed_terms ) && is_array( $allowed_terms ) ) {
                $intersection = array_intersect( $post_terms, $allowed_terms );
                if ( ! empty( $intersection ) ) {
                    return true; // This post has terms that are restricted
                }
            }
        }

        return false; // No restrictions found for this post's terms
    }
}
