Code/Core/NetworkStorageRevisionUI.cs
using System;
using System.Threading.Tasks;
using Sandbox.UI;

namespace Sandbox;

public static partial class NetworkStorage
{
	/// <summary>
	/// Open the outdated revision message panel.
	/// Requires a parent panel to attach to. If parent is null,
	/// a warning is logged and no UI is created, but the
	/// <see cref="OnRevisionOutdated"/> hook still fires.
	/// </summary>
	public static void OpenRevisionOutdatedMessage( Panel parent = null )
	{
		NetworkStorageOutdatedUI.Open( parent );
	}

	/// <summary>
	/// Close the outdated revision message panel if it is open.
	/// </summary>
	public static void CloseRevisionOutdatedMessage()
	{
		NetworkStorageOutdatedUI.Close();
	}

	/// <summary>
	/// Toggle the outdated revision message panel open/closed.
	/// </summary>
	public static void ToggleRevisionOutdatedMessage( Panel parent = null )
	{
		if ( NetworkStorageOutdatedUI.IsOpen )
		{
			NetworkStorageOutdatedUI.Close();
		}
		else
		{
			NetworkStorageOutdatedUI.Open( parent );
		}
	}

	/// <summary>
	/// Refresh the lobby list to find lobbies running the latest revision.
	/// This is a stub — game code should override with actual lobby query logic
	/// by subscribing to <see cref="OnRefreshLobbyListRequested"/>.
	/// </summary>
	public static async Task RefreshRevisionLobbyListAsync()
	{
		// Fire the request — game code should handle this
		OnRefreshLobbyListRequested?.Invoke();

		// Default implementation: log and return
		await Task.CompletedTask;
	}

	/// <summary>
	/// Fired when <see cref="RefreshRevisionLobbyListAsync"/> is called.
	/// Game code should subscribe and perform the actual lobby refresh.
	/// </summary>
	public static event Action OnRefreshLobbyListRequested;

	// ── Test / Debug APIs ──

	/// <summary>
	/// Simulate an outdated revision detection for testing.
	/// Creates a fake <see cref="RevisionOutdatedData"/> with
	/// <c>Reason = ManualTest</c> and fires the full UI pipeline:
	/// - Updates <see cref="NetworkStoragePackageInfo"/> state
	/// - Fires <see cref="OnRevisionOutdated"/> for custom hooks
	/// - Opens the default message panel (if configured)
	///
	/// Does NOT require the backend to report a mismatch.
	/// Bypasses <see cref="RevisionSettings.ShowOnlyOnce"/>.
	/// Logs clearly that this is a test.
	/// </summary>
	public static void TestShowRevisionOutdatedMessage( Panel parent = null )
	{
		Log.Warning( "[NetworkStorage] TEST: Simulating outdated revision detection (no backend required)" );

		var data = new RevisionOutdatedData
		{
			CurrentRevisionId = NetworkStoragePackageInfo.CurrentRevisionId ?? 1,
			LatestRevisionId = (NetworkStoragePackageInfo.CurrentRevisionId ?? 1) + 1,
			RevisionOutdated = true,
			GraceSeconds = 120,
			GraceEndsAtUnixSeconds = DateTimeOffset.UtcNow.ToUnixTimeSeconds() + 120,
			ServerUnixSeconds = DateTimeOffset.UtcNow.ToUnixTimeSeconds(),
			Source = "manual-test",
			Reason = RevisionOutdatedReason.ManualTest,
		};

		// Update package info state
		NetworkStoragePackageInfo.UpdateFromRevisionBlock( data );

		// Fire the event for custom hooks
		OnRevisionOutdated?.Invoke( data );

		// Open the default UI
		NetworkStorageOutdatedUI.ForceOpen( parent );
	}

	/// <summary>
	/// Fire the <see cref="OnRevisionOutdated"/> event with test data.
	/// Does NOT show the default UI — only fires the event so game code
	/// can test custom hooks without interference from the default panel.
	/// Logs clearly that this is a test.
	/// </summary>
	public static void TestFireRevisionOutdated()
	{
		Log.Warning( "[NetworkStorage] TEST: Firing OnRevisionOutdated event only (no UI)" );

		var data = new RevisionOutdatedData
		{
			CurrentRevisionId = NetworkStoragePackageInfo.CurrentRevisionId ?? 1,
			LatestRevisionId = (NetworkStoragePackageInfo.CurrentRevisionId ?? 1) + 1,
			RevisionOutdated = true,
			GraceSeconds = 120,
			GraceEndsAtUnixSeconds = DateTimeOffset.UtcNow.ToUnixTimeSeconds() + 120,
			ServerUnixSeconds = DateTimeOffset.UtcNow.ToUnixTimeSeconds(),
			Source = "manual-test",
			Reason = RevisionOutdatedReason.ManualTest,
		};

		// Fire the event only — no UI, no package info update
		OnRevisionOutdated?.Invoke( data );
	}
}