<?php
/**
 * Protection engine — hooks into WordPress to intercept protected content.
 *
 * @package PrivexPasswordProtect
 */

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

/**
 * Class PPMSTR_Protection_Engine
 */
class PPMSTR_Protection_Engine {

	/**
	 * @var PPMSTR_Access_Checker
	 */
	private $access;

	/**
	 * @var PPMSTR_Cookie_Manager
	 */
	private $cookies;

	/**
	 * @var bool
	 */
	private $form_error = false;

	/**
	 * @var string Type of error (post, site, category, child, shortcode).
	 */
	private $error_type = '';

	/**
	 * @var int|string Error target (post_id, term_id, instance_id).
	 */
	private $error_target = 0;

	/**
	 * @var string Specific error message to show (overrides default).
	 */
	private $error_message = '';

	/**
	 * Constructor.
	 *
	 * @param PPMSTR_Access_Checker $access  Access checker.
	 * @param PPMSTR_Cookie_Manager $cookies Cookie manager.
	 */
	public function __construct( PPMSTR_Access_Checker $access, PPMSTR_Cookie_Manager $cookies ) {
		$this->access  = $access;
		$this->cookies = $cookies;
	}

	/**
	 * Register hooks.
	 */
	public function init() {
		add_action( 'init', array( $this, 'process_form_submission' ), 5 );
		add_action( 'template_redirect', array( $this, 'maybe_render_template_preview' ), 1 );
		add_action( 'template_redirect', array( $this, 'check_site_protection' ) );
		add_filter( 'the_content', array( $this, 'filter_protected_content' ), 999 );
	}

	/**
	 * Admin-only live preview of a template via ?ppmstr_preview=<id>.
	 */
	public function maybe_render_template_preview() {
		if ( empty( $_GET['ppmstr_preview'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
			return;
		}
		if ( ! current_user_can( 'manage_options' ) ) {
			return;
		}

		$template_id = sanitize_key( wp_unslash( $_GET['ppmstr_preview'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended

		if ( ! class_exists( 'PPMSTR_Template_Builder' ) ) {
			require_once PPMSTR_PLUGIN_DIR . 'admin/class-ppmstr-template-builder.php';
		}
		$tpl = PPMSTR_Template_Builder::get_template( $template_id );
		if ( ! $tpl ) {
			return;
		}

		$args = array(
			'post_id'     => 0,
			'type'        => 'site',
			'error'       => ! empty( $_GET['ppmstr_preview_error'] ), // phpcs:ignore WordPress.Security.NonceVerification.Recommended
			'headline'    => __( 'This Site is Protected', 'privex-password-protect' ),
			'description' => __( 'Please enter the password to continue.', 'privex-password-protect' ),
			'button_text' => __( 'Unlock', 'privex-password-protect' ),
			'placeholder' => __( 'Enter password…', 'privex-password-protect' ),
			'error_msg'   => __( 'Incorrect password. Please try again.', 'privex-password-protect' ),
		);
		$nonce = wp_create_nonce( 'ppmstr_preview_' . $template_id );

		$form_html = PPMSTR_Template_Builder::render( $tpl, $args, $nonce, true );

		nocache_headers();
		?>
		<!DOCTYPE html>
		<html <?php language_attributes(); ?>>
		<head>
			<meta charset="<?php bloginfo( 'charset' ); ?>" />
			<meta name="viewport" content="width=device-width, initial-scale=1" />
			<title><?php echo esc_html( $tpl['name'] ?? 'Preview' ); ?> — <?php esc_html_e( 'Template Preview', 'privex-password-protect' ); ?></title>
			<?php
			wp_enqueue_style( 'ppmstr-public', PPMSTR_PLUGIN_URL . 'assets/css/ppmstr-public.css', array(), PPMSTR_VERSION );
			wp_add_inline_style( 'ppmstr-public', 'html,body{margin:0;padding:0;font-family:-apple-system,BlinkMacSystemFont,\'Segoe UI\',Roboto,\'Helvetica Neue\',Arial,sans-serif;}' );
			wp_print_styles( 'ppmstr-public' );
			?>
		</head>
		<body>
			<?php echo $form_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- rendered by template builder. ?>
		</body>
		</html>
		<?php
		exit;
	}

	/**
	 * Process password form submission.
	 */
	public function process_form_submission() {
		if ( is_admin() ) {
			return;
		}

		if ( ! isset( $_POST['ppmstr_password'] ) || '' === $_POST['ppmstr_password'] ) {
			return;
		}

		$nonce_field = isset( $_POST['ppmstr_nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['ppmstr_nonce'] ) ) : '';
		$type        = isset( $_POST['ppmstr_type'] ) ? sanitize_key( $_POST['ppmstr_type'] ) : '';
		$post_id     = isset( $_POST['ppmstr_post_id'] ) ? absint( $_POST['ppmstr_post_id'] ) : 0;
		$password    = trim( sanitize_text_field( wp_unslash( $_POST['ppmstr_password'] ) ) );
		$valid       = false;
		$redirect    = '';

		// Phase 6: Limit Login Check (Brute Force)
		$bf_check = PPMSTR_Security_Handler::check_brute_force();
		if ( true !== $bf_check ) {
			$this->form_error    = true;
			$this->error_type    = $type;
			$this->error_target  = $post_id;
			$this->error_message = $bf_check;
			return;
		}

		// Phase 6: CAPTCHA Verification
		$captcha_check = PPMSTR_Security_Handler::verify_captcha();
		if ( true !== $captcha_check ) {
			$this->form_error    = true;
			$this->error_type    = $type;
			$this->error_target  = $post_id;
			$this->error_message = $captcha_check;
			return;
		}

		switch ( $type ) {
			case 'site':
				if ( ! wp_verify_nonce( $nonce_field, 'ppmstr_password_site' ) ) {
					$this->form_error = true;
					return;
				}
				$validator = new PPMSTR_Password_Validator();
				// Check master password first.
				if ( $validator->validate_master( $password ) ) {
					$this->cookies->set_master_cookie();
					$valid = true;
				} else {
					$valid = $validator->validate_for_site( $password );
					if ( $valid ) {
						$this->cookies->set_site_cookie();
					}
				}
				$redirect = home_url( '/' );
				break;

			case 'post':
				if ( ! wp_verify_nonce( $nonce_field, 'ppmstr_password_' . $post_id ) ) {
					$this->form_error = true;
					return;
				}
				$validator  = new PPMSTR_Password_Validator();
				$result     = $validator->validate_for_post( $password, $post_id );
				if ( 'master' === $result ) {
					$this->cookies->set_master_cookie();
					$valid = true;
				} elseif ( $result ) {
					$this->cookies->set_post_cookie( $post_id );
					$valid = true;
				}
				$redirect = get_permalink( $post_id );
				break;

			case 'category':
				$term_id = isset( $_POST['ppmstr_term_id'] ) ? absint( $_POST['ppmstr_term_id'] ) : 0;
				if ( ! wp_verify_nonce( $nonce_field, 'ppmstr_password_cat_' . $term_id ) ) {
					$this->form_error = true;
					return;
				}
				$validator = new PPMSTR_Password_Validator();
				$valid     = $validator->validate_for_category( $password, $term_id );
				if ( $valid ) {
					// Check if it was unlocked via master password.
					if ( $validator->validate_master( $password ) ) {
						$this->cookies->set_master_cookie();
					} else {
						$this->cookies->set_category_cookie( $term_id );
					}
				}
				$redirect = get_permalink( $post_id ) ?: home_url( '/' );
				break;

			case 'post_type':
				$pt_slug = isset( $_POST['ppmstr_post_type'] ) ? sanitize_key( $_POST['ppmstr_post_type'] ) : '';
				if ( ! wp_verify_nonce( $nonce_field, 'ppmstr_password_pt_' . $pt_slug ) ) {
					$this->form_error = true;
					return;
				}
				$validator = new PPMSTR_Password_Validator();
				$valid     = $validator->validate_for_post_type( $password, $pt_slug );
				if ( $valid ) {
					// Check if it was unlocked via master password.
					if ( $validator->validate_master( $password ) ) {
						$this->cookies->set_master_cookie();
					} else {
						$this->cookies->set_post_type_cookie( $pt_slug );
					}
				}
				$redirect = get_permalink( $post_id ) ?: home_url( '/' );
				break;

			case 'child':
				$parent_id = isset( $_POST['ppmstr_parent_id'] ) ? absint( $_POST['ppmstr_parent_id'] ) : 0;
				if ( ! wp_verify_nonce( $nonce_field, 'ppmstr_password_' . $parent_id ) ) {
					$this->form_error = true;
					return;
				}
				$validator = new PPMSTR_Password_Validator();
				$valid     = $validator->validate_for_post( $password, $parent_id );
				if ( $valid ) {
					$this->cookies->set_post_cookie( $parent_id );
				}
				$redirect = get_permalink( $post_id ) ?: home_url( '/' );
				break;

			case 'shortcode':
				$instance_id = isset( $_POST['ppmstr_instance'] ) ? sanitize_key( $_POST['ppmstr_instance'] ) : '';
				if ( ! wp_verify_nonce( $nonce_field, 'ppmstr_password_sc_' . $instance_id ) ) {
					$this->form_error = true;
					return;
				}
				$stored_hash = isset( $_POST['ppmstr_hash'] ) ? sanitize_text_field( wp_unslash( $_POST['ppmstr_hash'] ) ) : '';
				$valid       = wp_check_password( $password, $stored_hash );
				if ( $valid ) {
					$this->cookies->set_shortcode_cookie( $instance_id, $password );
				}
				$redirect = $post_id ? get_permalink( $post_id ) : wp_get_referer();
				if ( ! $valid && $redirect ) {
					$redirect = add_query_arg( 'ppmstr_sc_error', $instance_id, $redirect );
				}
				break;

			default:
				return;
		}

		if ( $valid && $redirect ) {
			PPMSTR_Security_Handler::reset_failed_attempts();
			PPMSTR_Security_Handler::register_session();
			wp_safe_redirect( esc_url_raw( $redirect ) );
			exit;
		}

		PPMSTR_Security_Handler::record_failed_attempt();
		$this->form_error   = true;
		$this->error_type   = $type;
		$this->error_target = $post_id;
	}

	/**
	 * Check site-wide protection on template_redirect.
	 */
	public function check_site_protection() {
		if ( is_admin() ) {
			return;
		}
		if ( $this->is_login_page() ) {
			return;
		}

		$settings = get_option( 'ppmstr_settings', array() );
		$template = isset( $settings['active_template'] ) ? sanitize_file_name( $settings['active_template'] ) : 'default';
        $site_locked = ! $this->access->can_access_site();
        
        $args = array();
        $nonce = '';

		// Check handling for specifically protected posts.
		if ( is_singular() ) {
			$post_id = get_queried_object_id();
			if ( $this->access->is_excluded( $post_id ) ) {
                if ( ! $site_locked ) {
                    return; 
                }
			} else {
                // Determine if this post has its own protection that needs a full-page wall.
                if ( ! $this->access->can_fully_access_post( $post_id ) ) {
                    
                    if ( $this->access->is_post_protected( $post_id ) && ! $this->access->can_access_post( $post_id ) ) {
                        $args['type']        = 'post';
                        $args['post_id']     = $post_id;
                        $nonce               = wp_create_nonce( 'ppmstr_password_' . $post_id );
                        $args['headline']    = __( 'This Post is Protected', 'privex-password-protect' );
                        $custom_msg          = get_post_meta( $post_id, '_ppmstr_error_message', true );
                        $args['error_msg']   = ( $this->form_error && $this->error_message ) ? $this->error_message : ( ! empty( $custom_msg ) ? $custom_msg : __( 'Incorrect password for this post.', 'privex-password-protect' ) );
                    } elseif ( $this->access->is_post_type_protected( get_post_type( $post_id ) ) && ! $this->access->can_access_via_post_type( $post_id ) ) {
                        $args['type']        = 'post_type';
                        $args['post_type']   = get_post_type( $post_id );
                        $args['post_id']     = $post_id;
                        $nonce               = wp_create_nonce( 'ppmstr_password_pt_' . get_post_type( $post_id ) );
                        $args['headline']    = __( 'This Content is Protected', 'privex-password-protect' );
                    } elseif ( $this->access->is_in_protected_category( $post_id ) && ! $this->access->can_access_via_category( $post_id ) ) {
                        $args['type']        = 'category';
                        $term_id             = $this->access->get_protected_category_for_post( $post_id );
                        $args['term_id']     = $term_id;
                        $args['post_id']     = $post_id;
                        $nonce               = wp_create_nonce( 'ppmstr_password_cat_' . $term_id );
                        $args['headline']    = __( 'Category Protected', 'privex-password-protect' );
                    } elseif ( $this->access->has_protected_ancestor( $post_id ) && ! $this->access->can_access_as_child( $post_id ) ) {
                        $args['type']        = 'child';
                        $parent_id           = $this->access->get_protected_ancestor( $post_id );
                        $args['parent_id']   = $parent_id;
                        $args['post_id']     = $post_id;
                        $nonce               = wp_create_nonce( 'ppmstr_password_' . $parent_id );
                        $args['headline']    = __( 'This Area is Protected', 'privex-password-protect' );
                    }
                    
                    if ( ! empty( $args ) ) {
                        $args['error']       = ( $this->form_error && $args['type'] === $this->error_type );
                        $args['description'] = __( 'Please enter the password to view this content.', 'privex-password-protect' );
                        $args['button_text'] = __( 'Unlock Content', 'privex-password-protect' );
                        $args['placeholder'] = __( 'Enter password…', 'privex-password-protect' );
                        if ( empty( $args['error_msg'] ) ) {
                            $args['error_msg'] = ( $this->form_error && $this->error_message ) ? $this->error_message : __( 'Incorrect password. Please try again.', 'privex-password-protect' );
                        }
                    }
                } else {
                    // They unlocked specific post, let them see it (bypass site lock).
                    if ( $this->access->is_post_protected( $post_id ) || 
                         $this->access->is_in_protected_category( $post_id ) || 
                         $this->access->is_post_type_protected( get_post_type( $post_id ) ) ||
                         $this->access->has_protected_ancestor( $post_id ) ) {
                        return;
                    }
                }
            }
		}

        // Fallback to site-wide wall if no specific post wall was generated
        if ( empty( $args ) ) {
            if ( ! $site_locked ) {
                return;
            }

            $args = array(
                'post_id'     => 0,
                'type'        => 'site',
                'error'       => ( $this->form_error && 'site' === $this->error_type ),
                'headline'    => isset( $settings['form_headline'] ) ? $settings['form_headline'] : __( 'This Site is Protected', 'privex-password-protect' ),
                'description' => isset( $settings['form_description'] ) ? $settings['form_description'] : __( 'Please enter the password to continue.', 'privex-password-protect' ),
                'button_text' => isset( $settings['form_button_text'] ) ? $settings['form_button_text'] : __( 'Unlock', 'privex-password-protect' ),
                'placeholder' => isset( $settings['form_placeholder'] ) ? $settings['form_placeholder'] : __( 'Enter password…', 'privex-password-protect' ),
                'error_msg'   => ( $this->form_error && $this->error_message ) ? $this->error_message : ( isset( $settings['form_error_message'] ) ? $settings['form_error_message'] : __( 'Incorrect password. Please try again.', 'privex-password-protect' ) ),
            );
            $nonce = wp_create_nonce( 'ppmstr_password_site' );
        }

		// Builder template (preset or custom) — render full-page with builder blocks.
		// NOTE: We intentionally skip wp_head()/wp_footer() here to prevent theme CSS
		// from overriding template inline styles. Assets are loaded manually instead.
		if ( ! class_exists( 'PPMSTR_Template_Builder' ) ) {
			require_once PPMSTR_PLUGIN_DIR . 'admin/class-ppmstr-template-builder.php';
		}
		if ( PPMSTR_Template_Builder::is_builder_template( $template ) ) {
			$builder_tpl = PPMSTR_Template_Builder::get_template( $template );
			if ( $builder_tpl ) {
				$form_html   = PPMSTR_Template_Builder::render( $builder_tpl, $args, $nonce, true );
				$public_css  = esc_url( PPMSTR_PLUGIN_URL . 'assets/css/ppmstr-public.css' );
				$public_js   = esc_url( PPMSTR_PLUGIN_URL . 'assets/js/ppmstr-public.js' );
				$ver         = esc_attr( PPMSTR_VERSION );
				$ajax_url    = esc_url( admin_url( 'admin-ajax.php' ) );
				nocache_headers();
				?>
				<!DOCTYPE html>
				<html <?php language_attributes(); ?>>
				<head>
					<meta charset="<?php bloginfo( 'charset' ); ?>" />
					<meta name="viewport" content="width=device-width, initial-scale=1" />
					<title><?php echo esc_html( $args['headline'] ); ?> — <?php bloginfo( 'name' ); ?></title>
					<?php
					wp_enqueue_style( 'ppmstr-public', PPMSTR_PLUGIN_URL . 'assets/css/ppmstr-public.css', array(), PPMSTR_VERSION );
					wp_print_styles( 'ppmstr-public' );
					?>
				</head>
				<body style="margin:0;padding:0;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif;">
					<?php echo $form_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- rendered by template builder with escaping. ?>
					<?php
					wp_enqueue_script( 'ppmstr-public', PPMSTR_PLUGIN_URL . 'assets/js/ppmstr-public.js', array(), PPMSTR_VERSION, true );
					wp_localize_script( 'ppmstr-public', 'ppmstrPublic', array( 'ajaxUrl' => admin_url( 'admin-ajax.php' ) ) );
					wp_print_scripts( 'ppmstr-public' );
					?>
				</body>
				</html>
				<?php
				exit;
			}
		}

		wp_enqueue_style( 'ppmstr-public', PPMSTR_PLUGIN_URL . 'assets/css/ppmstr-public.css', array(), PPMSTR_VERSION );
		$tpl_css = PPMSTR_PLUGIN_DIR . 'templates/' . $template . '/style.css';
		if ( file_exists( $tpl_css ) ) {
			wp_enqueue_style( 'ppmstr-template-' . $template, PPMSTR_PLUGIN_URL . 'templates/' . $template . '/style.css', array( 'ppmstr-public' ), PPMSTR_VERSION );
		}
		wp_enqueue_script( 'ppmstr-public', PPMSTR_PLUGIN_URL . 'assets/js/ppmstr-public.js', array(), PPMSTR_VERSION, true );
		wp_localize_script(
			'ppmstr-public',
			'ppmstrPublic',
			array(
				'ajaxUrl' => esc_url( admin_url( 'admin-ajax.php' ) ),
			)
		);

		$full_page = PPMSTR_PLUGIN_DIR . 'templates/' . $template . '/full-page.php';
		if ( ! file_exists( $full_page ) ) {
			$full_page = PPMSTR_PLUGIN_DIR . 'templates/default/full-page.php';
		}
		include $full_page;
		exit;
	}

	/**
	 * Filter the_content to replace protected post content with a password form.
	 *
	 * @param string $content Original content.
	 * @return string
	 */
	public function filter_protected_content( $content ) {
		if ( is_admin() ) {
			return $content;
		}
		$post_id = get_the_ID();
		if ( ! $post_id ) {
			return $content;
		}

		$settings = get_option( 'ppmstr_settings', array() );

		// Check individual post protection.
		if ( $this->access->is_post_protected( $post_id ) ) {
			if ( ! $this->access->can_access_post( $post_id ) ) {
				return $this->render_post_form( $post_id, $settings );
			}
		} elseif ( $this->access->is_post_type_protected( get_post_type( $post_id ) ) ) {
			// Check post type protection.
			if ( ! $this->access->can_access_via_post_type( $post_id ) ) {
				return $this->render_post_type_form( $post_id, $settings );
			}
		} elseif ( $this->access->is_in_protected_category( $post_id ) ) {
			// Check category protection.
			if ( ! $this->access->can_access_via_category( $post_id ) ) {
				return $this->render_category_form( $post_id, $settings );
			}
		} elseif ( $this->access->has_protected_ancestor( $post_id ) ) {
			// Check child page inheritance.
			if ( ! $this->access->can_access_as_child( $post_id ) ) {
				$parent_id = $this->access->get_protected_ancestor( $post_id );
				return $this->render_child_form( $post_id, $parent_id, $settings );
			}
		}

		return $content;
	}

	/**
	 * Render password form for individual post protection.
	 *
	 * @param int   $post_id  Post ID.
	 * @param array $settings Plugin settings.
	 * @return string
	 */
	private function render_post_form( $post_id, $settings ) {
		$template = isset( $settings['active_template'] ) ? sanitize_file_name( $settings['active_template'] ) : 'default';
		$post_tpl = get_post_meta( $post_id, '_ppmstr_template', true );
		if ( $post_tpl ) {
			$template = sanitize_file_name( $post_tpl );
		}

		$args = array(
			'post_id'     => $post_id,
			'type'        => 'post',
			'error'       => ( $this->form_error && 'post' === $this->error_type ),
			'headline'    => isset( $settings['form_headline'] ) ? $settings['form_headline'] : __( 'This Content is Protected', 'privex-password-protect' ),
			'description' => isset( $settings['form_description'] ) ? $settings['form_description'] : '',
			'button_text' => isset( $settings['form_button_text'] ) ? $settings['form_button_text'] : __( 'Unlock', 'privex-password-protect' ),
			'placeholder' => isset( $settings['form_placeholder'] ) ? $settings['form_placeholder'] : __( 'Enter password…', 'privex-password-protect' ),
			'error_msg'   => ( $this->form_error && $this->error_message ) ? $this->error_message : ( isset( $settings['form_error_message'] ) ? $settings['form_error_message'] : '' ),
		);

		$nonce = wp_create_nonce( 'ppmstr_password_' . $post_id );

		if ( ! class_exists( 'PPMSTR_Template_Builder' ) ) {
			require_once PPMSTR_PLUGIN_DIR . 'admin/class-ppmstr-template-builder.php';
		}
		if ( PPMSTR_Template_Builder::is_builder_template( $template ) ) {
			$builder_tpl = PPMSTR_Template_Builder::get_template( $template );
			if ( $builder_tpl ) {
				return PPMSTR_Template_Builder::render( $builder_tpl, $args, $nonce );
			}
		}

		$tpl_file = $this->locate_template( $template );
		ob_start();
		include $tpl_file;
		return ob_get_clean();
	}

	/**
	 * Render password form for category protection.
	 *
	 * @param int   $post_id  Post ID.
	 * @param array $settings Plugin settings.
	 * @return string
	 */
	private function render_category_form( $post_id, $settings ) {
		$term_id  = $this->access->get_protected_category_for_post( $post_id );
		$template = isset( $settings['active_template'] ) ? sanitize_file_name( $settings['active_template'] ) : 'default';

		$args = array(
			'post_id'     => $post_id,
			'type'        => 'category',
			'term_id'     => $term_id,
			'error'       => ( $this->form_error && 'category' === $this->error_type ),
			'headline'    => isset( $settings['form_headline'] ) ? $settings['form_headline'] : __( 'This Content is Protected', 'privex-password-protect' ),
			'description' => isset( $settings['form_description'] ) ? $settings['form_description'] : '',
			'button_text' => isset( $settings['form_button_text'] ) ? $settings['form_button_text'] : __( 'Unlock', 'privex-password-protect' ),
			'placeholder' => isset( $settings['form_placeholder'] ) ? $settings['form_placeholder'] : __( 'Enter password…', 'privex-password-protect' ),
			'error_msg'   => ( $this->form_error && $this->error_message ) ? $this->error_message : ( isset( $settings['form_error_message'] ) ? $settings['form_error_message'] : '' ),
		);

		$nonce = wp_create_nonce( 'ppmstr_password_cat_' . $term_id );

		if ( ! class_exists( 'PPMSTR_Template_Builder' ) ) {
			require_once PPMSTR_PLUGIN_DIR . 'admin/class-ppmstr-template-builder.php';
		}
		if ( PPMSTR_Template_Builder::is_builder_template( $template ) ) {
			$builder_tpl = PPMSTR_Template_Builder::get_template( $template );
			if ( $builder_tpl ) {
				return PPMSTR_Template_Builder::render( $builder_tpl, $args, $nonce );
			}
		}

		$tpl_file = $this->locate_template( $template );
		ob_start();
		include $tpl_file;
		return ob_get_clean();
	}

	/**
	 * Render password form for post type protection.
	 *
	 * @param int   $post_id  Post ID.
	 * @param array $settings Plugin settings.
	 * @return string
	 */
	private function render_post_type_form( $post_id, $settings ) {
		$template  = isset( $settings['active_template'] ) ? sanitize_file_name( $settings['active_template'] ) : 'default';
		$post_type = get_post_type( $post_id );

		$args = array(
			'post_id'     => $post_id,
			'type'        => 'post_type',
			'post_type'   => $post_type,
			'error'       => ( $this->form_error && 'post_type' === $this->error_type ),
			'headline'    => isset( $settings['form_headline'] ) ? $settings['form_headline'] : __( 'This Content is Protected', 'privex-password-protect' ),
			'description' => isset( $settings['form_description'] ) ? $settings['form_description'] : '',
			'button_text' => isset( $settings['form_button_text'] ) ? $settings['form_button_text'] : __( 'Unlock', 'privex-password-protect' ),
			'placeholder' => isset( $settings['form_placeholder'] ) ? $settings['form_placeholder'] : __( 'Enter password…', 'privex-password-protect' ),
			'error_msg'   => ( $this->form_error && $this->error_message ) ? $this->error_message : ( isset( $settings['form_error_message'] ) ? $settings['form_error_message'] : '' ),
		);

		$nonce = wp_create_nonce( 'ppmstr_password_pt_' . $post_type );

		if ( ! class_exists( 'PPMSTR_Template_Builder' ) ) {
			require_once PPMSTR_PLUGIN_DIR . 'admin/class-ppmstr-template-builder.php';
		}
		if ( PPMSTR_Template_Builder::is_builder_template( $template ) ) {
			$builder_tpl = PPMSTR_Template_Builder::get_template( $template );
			if ( $builder_tpl ) {
				return PPMSTR_Template_Builder::render( $builder_tpl, $args, $nonce );
			}
		}

		$tpl_file = $this->locate_template( $template );
		ob_start();
		include $tpl_file;
		return ob_get_clean();
	}

	/**
	 * Render password form for child page inheriting parent protection.
	 *
	 * @param int   $post_id   Post ID.
	 * @param int   $parent_id Protected ancestor ID.
	 * @param array $settings  Plugin settings.
	 * @return string
	 */
	private function render_child_form( $post_id, $parent_id, $settings ) {
		$template = isset( $settings['active_template'] ) ? sanitize_file_name( $settings['active_template'] ) : 'default';

		$args = array(
			'post_id'     => $post_id,
			'type'        => 'child',
			'parent_id'   => $parent_id,
			'error'       => ( $this->form_error && 'child' === $this->error_type ),
			'headline'    => isset( $settings['form_headline'] ) ? $settings['form_headline'] : __( 'This Content is Protected', 'privex-password-protect' ),
			'description' => isset( $settings['form_description'] ) ? $settings['form_description'] : '',
			'button_text' => isset( $settings['form_button_text'] ) ? $settings['form_button_text'] : __( 'Unlock', 'privex-password-protect' ),
			'placeholder' => isset( $settings['form_placeholder'] ) ? $settings['form_placeholder'] : __( 'Enter password…', 'privex-password-protect' ),
			'error_msg'   => ( $this->form_error && $this->error_message ) ? $this->error_message : ( isset( $settings['form_error_message'] ) ? $settings['form_error_message'] : '' ),
		);

		$nonce = wp_create_nonce( 'ppmstr_password_' . $parent_id );

		if ( ! class_exists( 'PPMSTR_Template_Builder' ) ) {
			require_once PPMSTR_PLUGIN_DIR . 'admin/class-ppmstr-template-builder.php';
		}
		if ( PPMSTR_Template_Builder::is_builder_template( $template ) ) {
			$builder_tpl = PPMSTR_Template_Builder::get_template( $template );
			if ( $builder_tpl ) {
				return PPMSTR_Template_Builder::render( $builder_tpl, $args, $nonce );
			}
		}

		$tpl_file = $this->locate_template( $template );
		ob_start();
		include $tpl_file;
		return ob_get_clean();
	}

	/**
	 * Check whether the current page is protected (for asset enqueuing).
	 *
	 * @return bool
	 */
	public function is_current_page_protected() {
		$settings = get_option( 'ppmstr_settings', array() );

		if ( ! empty( $settings['site_protection_enabled'] ) && ! empty( $settings['site_password'] ) ) {
			return true;
		}

		if ( is_singular() ) {
			$post_id = get_queried_object_id();
			if ( ! $this->access->can_fully_access_post( $post_id ) ) {
				return true;
			}
		}

		return false;
	}

	/**
	 * Locate a template file.
	 *
	 * @param string $slug Template slug.
	 * @return string
	 */
	private function locate_template( $slug ) {
		$theme = get_stylesheet_directory() . '/privex-password-protect/' . $slug . '/template.php';
		if ( file_exists( $theme ) ) {
			return $theme;
		}
		$plugin = PPMSTR_PLUGIN_DIR . 'templates/' . $slug . '/template.php';
		if ( file_exists( $plugin ) ) {
			return $plugin;
		}
		return PPMSTR_PLUGIN_DIR . 'templates/default/template.php';
	}

	/**
	 * Check if current request is for the login page.
	 *
	 * @return bool
	 */
	private function is_login_page() {
		$pagenow = isset( $GLOBALS['pagenow'] ) ? $GLOBALS['pagenow'] : '';
		return ( 'wp-login.php' === $pagenow || 'wp-register.php' === $pagenow );
	}
}
