Editor/Serialization/DriftDialog.cs
using System;
using Editor;
using Sandbox;

namespace Grains.RazorDesigner.Serialization;

public sealed class DriftDialog
{
	private const string LogPrefix = "[Grains.RazorDesigner]";

	private readonly Widget _parent;

	public DriftDialog( Widget parent )
	{
		_parent = parent;
	}

	public enum Choice { ReImport, Discard, Cancel }

	public void Show( string razorPath, string jsonPath, Action<Choice> onChoice )
	{
		var dialog = new Editor.Dialog( _parent );
		dialog.Window.WindowTitle = "Razor File Edited Outside Designer";
		dialog.Window.SetWindowIcon( "warning" );
		dialog.Window.SetModal( true, true );
		dialog.Window.MinimumWidth = 460;

		dialog.Layout = Layout.Column();
		dialog.Layout.Margin = 16;
		dialog.Layout.Spacing = 10;

		// Explanation
		var body = new Editor.Label( dialog )
		{
			Text = "The .razor file has been edited outside the designer — it is newer " +
			       "than the canonical .razor.json.\n\n" +
			       "Choose how to proceed:",
			WordWrap = true,
		};
		dialog.Layout.Add( body );

		// File paths for context
		var pathLabel = new Editor.Label( dialog )
		{
			Text = $".razor:      {razorPath}\n.razor.json: {jsonPath}",
			WordWrap = true,
		};
		pathLabel.SetStyles( "color: #888; font-size: 10px; font-family: monospace;" );
		dialog.Layout.Add( pathLabel );

		// Separator
		dialog.Layout.AddSeparator();

		// Button row
		var buttonRow = dialog.Layout.Add( Layout.Row() );
		buttonRow.Spacing = 6;
		buttonRow.AddStretchCell();

		// Cancel (leftmost — least prominent)
		var cancelBtn = new Editor.Button( dialog ) { Text = "Cancel", MinimumWidth = 80 };
		cancelBtn.MouseLeftPress += () =>
		{
			Log.Info( $"{LogPrefix} DriftDialog: user chose Cancel" );
			dialog.Close();
			onChoice?.Invoke( Choice.Cancel );
		};
		buttonRow.Add( cancelBtn );

		var discardBtn = new Editor.Button( dialog ) { Text = "Discard external edits", MinimumWidth = 140 };
		discardBtn.MouseLeftPress += () =>
		{
			Log.Info( $"{LogPrefix} DriftDialog: user chose Discard" );
			dialog.Close();
			onChoice?.Invoke( Choice.Discard );
		};
		buttonRow.Add( discardBtn );

		// Re-import is the default / recommended action — rightmost (highest visual priority).
		var reimportBtn = new Editor.Button( dialog ) { Text = "Re-import changes", MinimumWidth = 130 };
		reimportBtn.MouseLeftPress += () =>
		{
			Log.Info( $"{LogPrefix} DriftDialog: user chose Re-import" );
			dialog.Close();
			onChoice?.Invoke( Choice.ReImport );
		};
		buttonRow.Add( reimportBtn );

		dialog.Window.AdjustSize();
		dialog.Show();

		// Default focus on Re-import (spec: "Default focused button: Re-import").
		reimportBtn.Focus();

		Log.Info( $"{LogPrefix} DriftDialog: shown for {razorPath}" );
	}
}