<?php
/**
 * Content-hash cache for parse_blocks() during schema extraction.
 *
 * FAQ, HowTo, and content-suggestion paths share one parse per content blob
 * within a request. No full page HTML is stored.
 *
 * @package SEOvaultSEO\Schema
 */

namespace SEOvaultSEO\Schema;

use SEOvaultSEO\Utils\RequestCache;

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

/**
 * Request-scoped block parse memoization keyed by content hash.
 */
class SchemaBlockParseCache {

	const REQUEST_PREFIX = 'schema_blocks:';

	/**
	 * Parse counts for diagnostics.
	 *
	 * @var array{hits:int,misses:int}
	 */
	private static $stats = array(
		'hits'   => 0,
		'misses' => 0,
	);

	/**
	 * Reset stats (tests).
	 *
	 * @return void
	 */
	public static function reset_stats() {
		self::$stats = array(
			'hits'   => 0,
			'misses' => 0,
		);
	}

	/**
	 * @return array{hits:int,misses:int}
	 */
	public static function get_stats() {
		return self::$stats;
	}

	/**
	 * Stable content fingerprint (hex sha256).
	 *
	 * @param string $content Post content.
	 * @return string
	 */
	public static function content_hash( $content ) {
		return hash( 'sha256', (string) $content );
	}

	/**
	 * Parse blocks once per unique content string in this request.
	 *
	 * @param string $content Post content.
	 * @return array
	 */
	public static function parse( $content ) {
		$content = (string) $content;
		$hash    = self::content_hash( $content );
		$key     = self::REQUEST_PREFIX . $hash;

		if ( RequestCache::has( $key ) ) {
			++self::$stats['hits'];
			$cached = RequestCache::get( $key, array() );
			return is_array( $cached ) ? $cached : array();
		}

		++self::$stats['misses'];
		$blocks = function_exists( 'parse_blocks' ) ? parse_blocks( $content ) : array();
		if ( ! is_array( $blocks ) ) {
			$blocks = array();
		}
		RequestCache::set( $key, $blocks );

		return $blocks;
	}
}
