<?php
/**
 * Recent change tracker for live reload.
 *
 * Mirrors the Vibe AI pattern — a single transient holds a ring buffer of
 * recent changes. The browser polls a REST endpoint and shows a toast
 * notification or auto-reloads when its own user fires a mutation.
 *
 * Cheap: no DB schema, single option, auto-expires.
 */

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

class PCD_PC_Change_Tracker {

	const TRANSIENT_KEY = 'pcd_pc_recent_changes';
	const TTL           = 10 * MINUTE_IN_SECONDS;
	const MAX_ENTRIES   = 50;

	/**
	 * Record a change.
	 *
	 * @param array $args {
	 *     @type string $summary       Short human-readable summary, e.g. "Post created: Hello World".
	 *     @type string $action_label  Button label on the toast: "View", "Refresh", "Edit", etc.
	 *     @type string $url           Frontend URL (permalink or preview).
	 *     @type string $admin_url     Admin URL (post editor).
	 *     @type int    $post_id       Affected post ID (used to detect same-post auto-refresh).
	 *     @type bool   $force         If true, navigate immediately (no toast).
	 * }
	 */
	public static function mark( array $args = [] ): void {
		$defaults = [
			'summary'      => '',
			'action_label' => 'Refresh',
			'url'          => '',
			'admin_url'    => '',
			'post_id'      => 0,
			'force'        => false,
		];
		$args = wp_parse_args( $args, $defaults );

		$entry = [
			'timestamp' => microtime( true ),
			'user_id'   => get_current_user_id(),
			'summary'   => sanitize_text_field( $args['summary'] ),
			'post_id'   => absint( $args['post_id'] ),
			'action'    => [
				'label'     => sanitize_text_field( $args['action_label'] ),
				'url'       => esc_url_raw( $args['url'] ),
				'admin_url' => esc_url_raw( $args['admin_url'] ),
				'force'     => (bool) $args['force'],
			],
		];

		$changes = get_transient( self::TRANSIENT_KEY );
		if ( ! is_array( $changes ) ) {
			$changes = [];
		}

		$changes[] = $entry;

		// Prune older than TTL + cap at MAX_ENTRIES.
		$cutoff  = microtime( true ) - self::TTL;
		$changes = array_values( array_filter( $changes, function ( $c ) use ( $cutoff ) {
			return isset( $c['timestamp'] ) && $c['timestamp'] > $cutoff;
		} ) );
		if ( count( $changes ) > self::MAX_ENTRIES ) {
			$changes = array_slice( $changes, -self::MAX_ENTRIES );
		}

		set_transient( self::TRANSIENT_KEY, $changes, self::TTL );
	}

	/**
	 * Get all changes recorded after a given microtime timestamp.
	 */
	public static function get_since( float $since = 0 ): array {
		$changes = get_transient( self::TRANSIENT_KEY );
		if ( ! is_array( $changes ) ) {
			return [];
		}
		$out = [];
		foreach ( $changes as $c ) {
			if ( isset( $c['timestamp'] ) && $c['timestamp'] > $since ) {
				$out[] = $c;
			}
		}
		return $out;
	}

	public static function has_recent(): bool {
		$changes = get_transient( self::TRANSIENT_KEY );
		return is_array( $changes ) && ! empty( $changes );
	}
}
