<?php
/**
 * Cookie management for unlocked content.
 *
 * @package PrivexPasswordProtect
 */

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

/**
 * Class PPMSTR_Cookie_Manager
 */
class PPMSTR_Cookie_Manager {

	const COOKIE_PREFIX = 'wp-postpass_ppmstr_';

	/**
	 * Set an access cookie for a specific post.
	 *
	 * @param int $post_id Post ID.
	 */
	public function set_post_cookie( $post_id ) {
		$this->set_cookie(
			self::COOKIE_PREFIX . absint( $post_id ),
			$this->generate_token( $post_id ),
			$this->get_duration()
		);
	}

	/**
	 * Set an access cookie for site-wide protection.
	 */
	public function set_site_cookie() {
		$this->set_cookie(
			self::COOKIE_PREFIX . 'site',
			$this->generate_token( 'site' ),
			$this->get_duration()
		);
	}

	/**
	 * Set an access cookie for a protected category.
	 *
	 * @param int $term_id Term ID.
	 */
	public function set_category_cookie( $term_id ) {
		$this->set_cookie(
			self::COOKIE_PREFIX . 'cat_' . absint( $term_id ),
			$this->generate_category_token( $term_id ),
			$this->get_duration()
		);
	}

	/**
	 * Set an access cookie for a shortcode instance.
	 *
	 * @param string $instance_id Instance identifier.
	 * @param string $password    Plain-text password for token generation.
	 */
	public function set_shortcode_cookie( $instance_id, $password ) {
		$token = wp_hash( 'ppmstr_sc_granted_' . $instance_id . '_' . $password );
		$this->set_cookie(
			self::COOKIE_PREFIX . 'sc_' . sanitize_key( $instance_id ),
			$token,
			$this->get_duration()
		);
	}

	/**
	 * Check if a valid post cookie exists.
	 *
	 * @param int $post_id Post ID.
	 * @return bool
	 */
	public function has_post_cookie( $post_id ) {
		$name     = self::COOKIE_PREFIX . absint( $post_id );
		$expected = $this->generate_token( $post_id );
		return $this->verify_cookie( $name, $expected );
	}

	/**
	 * Check if a valid site cookie exists.
	 *
	 * @return bool
	 */
	public function has_site_cookie() {
		return $this->verify_cookie( self::COOKIE_PREFIX . 'site', $this->generate_token( 'site' ) );
	}

	/**
	 * Check if a valid category cookie exists.
	 *
	 * @param int $term_id Term ID.
	 * @return bool
	 */
	public function has_category_cookie( $term_id ) {
		$name     = self::COOKIE_PREFIX . 'cat_' . absint( $term_id );
		$expected = $this->generate_category_token( $term_id );
		return $this->verify_cookie( $name, $expected );
	}

	/**
	 * Set an access cookie for a protected post type.
	 *
	 * @param string $post_type Post Type.
	 */
	public function set_post_type_cookie( $post_type ) {
		$this->set_cookie(
			self::COOKIE_PREFIX . 'pt_' . sanitize_key( $post_type ),
			$this->generate_post_type_token( $post_type ),
			$this->get_duration()
		);
	}

	/**
	 * Check if a valid post type cookie exists.
	 *
	 * @param string $post_type Post Type.
	 * @return bool
	 */
	public function has_post_type_cookie( $post_type ) {
		$name     = self::COOKIE_PREFIX . 'pt_' . sanitize_key( $post_type );
		$expected = $this->generate_post_type_token( $post_type );
		return $this->verify_cookie( $name, $expected );
	}

	/**
	 * Set a master password cookie (unlocks everything).
	 *
	 * ... (keep existing implementation)
	 */
	public function set_master_cookie() {
		$settings = get_option( 'ppmstr_settings', array() );
		$master   = isset( $settings['master_password'] ) ? $settings['master_password'] : '';
		$token    = wp_hash( 'ppmstr_master_granted_' . $master );
		$this->set_cookie(
			self::COOKIE_PREFIX . 'master',
			$token,
			$this->get_duration()
		);
	}

	/**
	 * Check if a valid master cookie exists.
	 *
	 * @return bool
	 */
	public function has_master_cookie() {
		$settings = get_option( 'ppmstr_settings', array() );
		$master   = isset( $settings['master_password'] ) ? $settings['master_password'] : '';
		if ( empty( $master ) ) {
			return false;
		}
		$expected = wp_hash( 'ppmstr_master_granted_' . $master );
		return $this->verify_cookie( self::COOKIE_PREFIX . 'master', $expected );
	}

	/**
	 * Generate a secure token for cookie value.
	 *
	 * @param mixed $identifier Post ID or 'site'.
	 * @return string
	 */
	private function generate_token( $identifier ) {
		$password_hash = '';
		if ( 'site' === $identifier ) {
			$settings      = get_option( 'ppmstr_settings', array() );
			$password_hash = isset( $settings['site_password'] ) ? $settings['site_password'] : '';
		} else {
			$password_hash = get_post_meta( absint( $identifier ), '_ppmstr_password', true );
		}
		return wp_hash( 'ppmstr_granted_' . $identifier . '_' . $password_hash );
	}

	/**
	 * Generate a secure token for category cookie.
	 *
	 * @param int $term_id Term ID.
	 * @return string
	 */
	private function generate_category_token( $term_id ) {
		$settings      = get_option( 'ppmstr_settings', array() );
		$password_hash = isset( $settings['category_password'] ) ? $settings['category_password'] : '';
		return wp_hash( 'ppmstr_cat_granted_' . absint( $term_id ) . '_' . $password_hash );
	}

	private function generate_post_type_token( $post_type ) {
		$settings      = get_option( 'ppmstr_settings', array() );
		$password_hash = $settings['post_type_password'] ?? '';
		return wp_hash( 'ppmstr_pt_granted_' . sanitize_key( $post_type ) . '_' . $password_hash );
	}

	/**
	 * Verify a cookie value.
	 *
	 * @param string $name     Cookie name.
	 * @param string $expected Expected value.
	 * @return bool
	 */
	private function verify_cookie( $name, $expected ) {
		if ( ! isset( $_COOKIE[ $name ] ) ) {
			return false;
		}

		if ( class_exists( 'PPMSTR_Security_Handler' ) && ! PPMSTR_Security_Handler::is_valid_session() ) {
			return false;
		}

		return hash_equals( $expected, sanitize_text_field( wp_unslash( $_COOKIE[ $name ] ) ) );
	}

	/**
	 * Get cookie duration in seconds.
	 *
	 * @return int
	 */
	private function get_duration() {
		$settings = get_option( 'ppmstr_settings', array() );
		$type     = isset( $settings['cookie_type'] ) ? $settings['cookie_type'] : 'persistent';
		if ( 'session' === $type ) {
			return 0;
		}
		$hours = isset( $settings['cookie_duration'] ) ? absint( $settings['cookie_duration'] ) : 24;
		return $hours * HOUR_IN_SECONDS;
	}

	/**
	 * Set a cookie safely.
	 *
	 * @param string $name     Cookie name.
	 * @param string $value    Cookie value.
	 * @param int    $duration Duration in seconds (0 = session).
	 */
	private function set_cookie( $name, $value, $duration ) {
		$expire = 0 === $duration ? 0 : time() + $duration;
		if ( PHP_VERSION_ID >= 70300 ) {
			setcookie(
				$name,
				$value,
				array(
					'expires'  => $expire,
					'path'     => COOKIEPATH,
					'domain'   => COOKIE_DOMAIN,
					'secure'   => is_ssl(),
					'httponly' => true,
					'samesite' => 'Lax',
				)
			);
		} else {
			setcookie( $name, $value, $expire, COOKIEPATH, COOKIE_DOMAIN, is_ssl(), true );
		}
		$_COOKIE[ $name ] = $value;
	}
}
