using System.Collections.Concurrent;
namespace AxCopilot.Services;
/// 알림 타입.
public enum NotificationType { Info, Success, Warning, Error }
/// 알림 항목.
public record NotificationEntry(
string Title,
string Message,
NotificationType Type,
DateTime Timestamp);
///
/// Phase L3-7: 알림 센터 — 앱 전체에서 알림을 발행하고 이력을 관리합니다.
/// 트레이 BalloonTip + 인앱 알림 큐를 결합합니다.
///
public static class NotificationCenterService
{
private const int MaxHistory = 50;
private static readonly ConcurrentQueue _history = new();
/// 새 알림 발행 이벤트. UI 계층에서 구독하여 인앱 알림 표시에 활용합니다.
public static event EventHandler? NotificationRaised;
/// 최근 알림 이력 (최대 50건, 최신 순).
public static IReadOnlyList History
{
get
{
var list = _history.ToArray();
Array.Reverse(list);
return list;
}
}
/// 알림을 발행합니다. 트레이 BalloonTip + 이벤트를 동시에 발화합니다.
public static void Show(string title, string message, NotificationType type = NotificationType.Info)
{
var entry = Record(title, message, type);
NotificationService.NotifyBalloonOnly(title, message);
TryRaise(entry);
}
/// 성공 알림.
public static void ShowSuccess(string title, string message)
=> Show(title, message, NotificationType.Success);
/// 경고 알림.
public static void ShowWarning(string title, string message)
=> Show(title, message, NotificationType.Warning);
/// 오류 알림.
public static void ShowError(string title, string message)
=> Show(title, message, NotificationType.Error);
/// 에이전트 작업 완료 알림 (BackgroundAgentService 전용 편의 메서드).
public static void NotifyAgentCompleted(string agentType, string? result)
{
var preview = result?.Length > 80 ? result[..77] + "…" : result ?? "완료";
Show($"{agentType} 에이전트 완료", preview, NotificationType.Success);
}
/// 이력을 초기화합니다.
public static void ClearHistory()
{
while (_history.TryDequeue(out _)) { }
}
internal static NotificationEntry Record(string title, string message, NotificationType type)
{
var entry = new NotificationEntry(title, message, type, DateTime.Now);
_history.Enqueue(entry);
while (_history.Count > MaxHistory && _history.TryDequeue(out _)) { }
TryRaise(entry);
return entry;
}
private static void TryRaise(NotificationEntry entry)
{
try { NotificationRaised?.Invoke(null, entry); }
catch (Exception) { }
}
}