<?php
/**
 * Handles tracking of active product viewers within a defined time window.
 *
 * @package Ilabs\Firevert\Modules\SpectatorViews\Services
 */

declare( strict_types=1 );

namespace Ilabs\Firevert\Modules\SpectatorViews\Services;

/**
 * Class SpectatorTrackingService
 */
class SpectatorTrackingService {

	/**
	 * Time window (in seconds) to consider a viewer as active.
	 *
	 * @var int
	 */
	private const WINDOW = 60;

	/**
	 * Registers the current visitor as active for the given product.
	 *
	 * @param int    $product_id    Product ID being viewed.
	 * @param string $visitor_hash  Unique hash identifying the visitor.
	 *
	 * @return int Number of active visitors.
	 */
	public function ping( int $product_id, string $visitor_hash ): int {
		$key      = $this->get_transient_key( $product_id );
		$visitors = get_transient( $key );

		if ( ! is_array( $visitors ) ) {
			$visitors = array();
		}

		$visitors[ $visitor_hash ] = time();

		$visitors = array_filter(
			$visitors,
			static function ( int $timestamp ): bool {
				return ( time() - $timestamp ) < self::WINDOW;
			}
		);

		set_transient( $key, $visitors, self::WINDOW );

		return count( $visitors );
	}

	/**
	 * Counts currently active visitors for a given product.
	 *
	 * @param int $product_id Product ID.
	 *
	 * @return int Number of currently active visitors.
	 */
	public function count_active( int $product_id ): int {
		$visitors = get_transient( $this->get_transient_key( $product_id ) );

		if ( ! is_array( $visitors ) ) {
			return 0;
		}

		$visitors = array_filter(
			$visitors,
			static function ( int $timestamp ): bool {
				return ( time() - $timestamp ) < self::WINDOW;
			}
		);

		return count( $visitors );
	}

	/**
	 * Generates a consistent transient key for a product.
	 *
	 * @param int $product_id Product ID.
	 *
	 * @return string Transient key string.
	 */
	private function get_transient_key( int $product_id ): string {
		return 'firevert_spectator_views_' . $product_id;
	}

	/**
	 * Generates a hashed visitor ID based solely on PHP session ID.
	 *
	 * @return string SHA256 hash of the session ID.
	 */
	public static function hash_visitor(): string {
		if ( session_status() === PHP_SESSION_NONE && ! headers_sent() ) {
			session_name( 'firevert_session' );
			session_start();
		}

		return hash( 'sha256', session_id() );
	}
}
