<?php
declare(strict_types=1);

namespace EHxMe\Metabox;

use EHxMe\Helpers\Helper;
use EHxMe\Services\Request;
use EHxMe\Services\Response;
use EHxMe\Services\Validator;

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

class PostContentRestriction
{
    public Response $response;
    public Validator $validator;

    /**
     * Constructor for PostContentRestriction class.
     *
     * Initializes necessary objects and hooks WordPress actions and filters.
     */
    public function __construct() 
    {
        $this->response = new Response();
        $this->validator = new Validator();

        add_action('add_meta_boxes', [$this, 'addMetaBoxes']);

        add_action('save_post', [$this, 'savePost'], 10, 2);

        add_filter('the_content', [$this, 'theContent']);
        add_action('pre_get_posts', [$this, 'preGetPosts']);            
    }

    /**
     * Adds meta boxes for content restriction settings to the 'post' and 'page' edit screens.
     *
     * @return void
     */
    public function addMetaBoxes()
    {
        add_meta_box(
            'ehxme_meta_box', 
            esc_html__('EHX Member: Content Restriction', 'ehx-members'),
            array($this, 'addInnerMetaBoxes'),
            ['post', 'page'], // Apply to both 'post' and 'page'
            'normal',
            'high'
        );            
    }

    /**
     * Adds the inner meta box content to the 'post' and 'page' edit screens.
     *
     * This function includes the inner metabox view file to display the content restriction settings.
     *
     * @param WP_Post $post The current post object being edited.
     *
     * @return void
     */
    public function addInnerMetaBoxes($post)
    {
        require_once EHXME_PLUGIN_DIR . 'views/admin/inc/inner-metabox.php';
    }

    /**
     * Filters the post content based on the content restriction settings.
     *
     * This function checks the content restriction settings for the current post and
     * modifies the post content accordingly. If the post is restricted, it shows a 404 page.
     *
     * @param string $content The original post content.
     *
     * @return string The modified post content.
     */
    public function theContent($content)
    {
        if (!is_singular()) {
            return $content;
        }

        $ehxme_content_restriction = get_post_meta(get_the_ID(), 'ehxme_content_restriction', true);

        if (!isset($ehxme_content_restriction['_ehx_accessible'])) {
            return $content;
        }

        $access_level = $ehxme_content_restriction['_ehx_accessible'];

        if ($access_level == 1 && is_user_logged_in()) {
            Helper::show_404();
        }
        elseif ($access_level == 2) {
            if (!is_user_logged_in()) {
                Helper::show_404();
            }
            
            $user = wp_get_current_user();
            $roles = (array) $user->roles;
            $access_roles = (array) ($ehxme_content_restriction['_ehx_access_roles'] ?? []);
            
            if (!array_intersect($roles, $access_roles)) {
                Helper::show_404();
            }
        }

        return $content;
    }

    /**
     * Modifies the main query to filter posts based on content restriction settings.
     *
     * This function checks the logged-in status and user roles to determine which posts should be included in the main query.
     * It modifies the meta query to include or exclude posts based on their content restriction settings.
     *
     * @param WP_Query $query The main query object.
     *
     * @return void
     */
    public function preGetPosts($query)
    {
        // Ensure this only runs on the frontend and for the main query
        if (is_singular() || is_admin() || !$query->is_main_query()) {
            return;
        }

        $user = wp_get_current_user();
        $user_roles = (array) $user->roles;
        $meta_query = [
            'relation' => 'OR',
            [
                'key'     => 'ehxme_content_restriction',
                'compare' => 'NOT EXISTS', // Include posts without the restriction meta key
            ],
        ];

        if (!is_user_logged_in()) { // Handle logged-out users (Exclude posts where `_ehx_accessible` is 2)
            $meta_query[] = [
                'key'     => 'ehxme_content_restriction',
                'value'   => '"_ehx_accessible";s:1:"2"',
                'compare' => 'NOT LIKE', // Exclude posts restricted to logged-in users
            ];
        }
        else { // Handle logged-in users with role-based access (Allow only posts they have access to)
            $role_conditions = [];
            foreach ($user_roles as $role) {
                $role_conditions[] = [
                    'key'     => 'ehxme_content_restriction',
                    'value'   => '"' . $role . '"',
                    'compare' => 'LIKE',
                ];
            }

            $meta_query[] = [
                'relation' => 'AND',
                [
                    'key'     => 'ehxme_content_restriction',
                    'value'   => '"_ehx_accessible";s:1:"2"',
                    'compare' => 'LIKE', // Must be access level 2
                ],
                [
                    'relation' => 'OR',
                    ...$role_conditions, // Check if user has one of the allowed roles
                ],
            ];
        }

        // Apply the modified meta query
        $query->set('meta_query', $meta_query);
    }

    /**
     * Saves the content restriction settings for a post when it is updated.
     *
     * This function verifies the nonce for security, prevents auto-saves, ensures the user has permission to edit the post,
     * and only proceeds if it's an edit post action. It then updates the post meta 'ehxme_content_restriction' with the new value
     * if it has changed.
     *
     * @param int $post_id The ID of the post being updated.
     *
     * @return void
     */
    public function savePost($post_id)
    {
        // Verify nonce for security
        if (!isset($_POST[Helper::NONCE_NAME]) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST[Helper::NONCE_NAME])), Helper::NONCE_NAME)) {
            return;
        }

        // Prevent auto-saves
        if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
            return;
        }

        // Ensure the user has permission to edit the post
        if (!current_user_can('edit_post', $post_id)) {
            return;
        }

        $request = new Request();
        
        // Only proceed if it's an edit post action
        if ($request->input('action') !== 'editpost') {
            return;
        }

        $field = 'ehxme_content_restriction';
        $new_value = $request->input($field);
        $old_value = get_post_meta($post_id, $field, true);

        // Update only if the value has changed
        if ($new_value !== $old_value) {
            update_post_meta($post_id, $field, $new_value);
        }
    }

}