// Copyright (c) 2025-2026 GeWuYou
// SPDX-License-Identifier: Apache-2.0

using GFramework.Core.Abstractions.Events;

namespace GFramework.Core.Events;

/// <summary>
///     支持优先级的泛型事件类
/// </summary>
/// <typeparam name="T">事件回调函数的参数类型</typeparam>
public class PriorityEvent<T> : IEvent
{
    /// <summary>
    ///     存储已注册的上下文事件处理器列表
    /// </summary>
    private readonly List<ContextEventHandler> _contextHandlers = new();

    /// <summary>
    ///     存储已注册的事件处理器列表
    /// </summary>
    private readonly List<EventHandler> _handlers = new();

    /// <summary>
    ///     保护处理器集合的并发访问
    /// </summary>
#if NET9_0_OR_GREATER
    // net9.0 及以上目标使用专用 Lock，以满足分析器对专用同步原语的建议。
    private readonly System.Threading.Lock _syncRoot = new();
#else
    // net8.0 目标仍回退到 object 锁，以保持多目标编译兼容性。
    private readonly object _syncRoot = new();
#endif

    /// <summary>
    ///     标记事件是否已被处理（用于 UntilHandled 传播模式）
    /// </summary>
    private bool _handled;

    /// <summary>
    ///     显式实现 IEvent 接口中的 Register 方法
    /// </summary>
    /// <param name="onEvent">无参事件处理方法</param>
    /// <returns>IUnRegister 对象，用于稍后注销该事件监听器</returns>
    IUnRegister IEvent.Register(Action onEvent)
    {
        return Register(_ => onEvent(), 0);
    }

    /// <summary>
    ///     注册一个事件监听器，默认优先级为 0
    /// </summary>
    /// <param name="onEvent">要注册的事件处理方法</param>
    /// <returns>IUnRegister 对象，用于稍后注销该事件监听器</returns>
    public IUnRegister Register(Action<T> onEvent)
    {
        return Register(onEvent, 0);
    }

    /// <summary>
    ///     注册一个事件监听器，并指定优先级
    /// </summary>
    /// <param name="onEvent">要注册的事件处理方法</param>
    /// <param name="priority">优先级，数值越大优先级越高</param>
    /// <returns>IUnRegister 对象，用于稍后注销该事件监听器</returns>
    public IUnRegister Register(Action<T> onEvent, int priority)
    {
        var handler = new EventHandler(onEvent, priority);
        lock (_syncRoot)
        {
            _handlers.Add(handler);

            // 按优先级降序排序（高优先级在前）
            _handlers.Sort((a, b) => b.Priority.CompareTo(a.Priority));
        }

        return new DefaultUnRegister(() => UnRegister(onEvent));
    }

    /// <summary>
    ///     取消指定的事件监听器
    /// </summary>
    /// <param name="onEvent">需要被注销的事件处理方法</param>
    public void UnRegister(Action<T> onEvent)
    {
        lock (_syncRoot)
        {
            _handlers.RemoveAll(h => h.Handler == onEvent);
        }
    }

    /// <summary>
    ///     注册一个上下文事件监听器，并指定优先级
    /// </summary>
    /// <param name="onEvent">要注册的事件处理方法，接收 EventContext 参数</param>
    /// <param name="priority">优先级，数值越大优先级越高</param>
    /// <returns>IUnRegister 对象，用于稍后注销该事件监听器</returns>
    public IUnRegister RegisterWithContext(Action<EventContext<T>> onEvent, int priority = 0)
    {
        var handler = new ContextEventHandler(onEvent, priority);
        lock (_syncRoot)
        {
            _contextHandlers.Add(handler);

            // 按优先级降序排序（高优先级在前）
            _contextHandlers.Sort((a, b) => b.Priority.CompareTo(a.Priority));
        }

        return new DefaultUnRegister(() => UnRegisterContext(onEvent));
    }

    /// <summary>
    ///     取消指定的上下文事件监听器
    /// </summary>
    /// <param name="onEvent">需要被注销的事件处理方法</param>
    public void UnRegisterContext(Action<EventContext<T>> onEvent)
    {
        lock (_syncRoot)
        {
            _contextHandlers.RemoveAll(h => h.Handler == onEvent);
        }
    }

    /// <summary>
    ///     触发事件处理程序，并指定传播模式
    /// </summary>
    /// <param name="t">传递给事件处理程序的参数</param>
    /// <param name="propagation">事件传播模式</param>
    public void Trigger(T t, EventPropagation propagation = EventPropagation.All)
    {
        _handled = false;

        switch (propagation)
        {
            case EventPropagation.All:
                TriggerAll(t);
                break;

            case EventPropagation.UntilHandled:
                TriggerUntilHandled(t);
                break;

            case EventPropagation.Highest:
                TriggerHighest(t);
                break;
        }
    }

    /// <summary>
    ///     触发所有事件处理器（按优先级顺序）
    /// </summary>
    /// <param name="t">事件参数</param>
    private void TriggerAll(T t)
    {
        var allHandlers = MergeAndSortHandlers(t);
        var context = new EventContext<T>(t);

        foreach (var item in allHandlers)
        {
            if (item.IsContext)
            {
                item.ContextHandler?.Invoke(context);
            }
            else
            {
                item.Handler?.Invoke();
            }
        }
    }

    /// <summary>
    ///     触发事件处理器直到被处理
    /// </summary>
    /// <param name="t">事件参数</param>
    private void TriggerUntilHandled(T t)
    {
        var allHandlers = MergeAndSortHandlers(t);
        var context = new EventContext<T>(t);

        foreach (var item in allHandlers)
        {
            if (item.IsContext)
            {
                item.ContextHandler?.Invoke(context);
                if (context.IsHandled) break;
            }
            else
            {
                item.Handler?.Invoke();
                if (_handled) break; // 保持向后兼容
            }
        }
    }

    /// <summary>
    ///     仅触发最高优先级的事件处理器
    /// </summary>
    /// <param name="t">事件参数</param>
    private void TriggerHighest(T t)
    {
        var (normalSnapshot, contextSnapshot) = CreateSnapshots();
        var highestPriority = GetHighestPriority(normalSnapshot, contextSnapshot);

        if (highestPriority != int.MinValue)
        {
            ExecuteHighPriorityNormalHandlers(normalSnapshot, t, highestPriority);
            ExecuteHighPriorityContextHandlers(contextSnapshot, t, highestPriority);
        }
    }

    /// <summary>
    ///     合并并排序所有事件处理器
    /// </summary>
    /// <param name="t">事件参数</param>
    /// <returns>合并排序后的处理器列表</returns>
    private List<(int Priority, Action? Handler, Action<EventContext<T>>? ContextHandler, bool IsContext)>
        MergeAndSortHandlers(T t)
    {
        var (normalSnapshot, contextSnapshot) = CreateSnapshots();
        // 使用统一的投影方法显式固定元组的可空标注，避免 LINQ 在 Concat 时推断出不兼容的签名。
        return normalSnapshot
            .Select(h => CreateNormalHandlerInvocation(h, t))
            .Concat(contextSnapshot.Select(CreateContextHandlerInvocation))
            .OrderByDescending(h => h.Priority)
            .ToList();
    }

    /// <summary>
    ///     获取最高优先级
    /// </summary>
    /// <param name="normalHandlers">普通事件处理器数组</param>
    /// <param name="contextHandlers">上下文事件处理器数组</param>
    /// <returns>最高优先级值</returns>
    private static int GetHighestPriority(EventHandler[] normalHandlers, ContextEventHandler[] contextHandlers)
    {
        var highestPriority = int.MinValue;

        if (normalHandlers.Length > 0)
            highestPriority = Math.Max(highestPriority, normalHandlers[0].Priority);

        if (contextHandlers.Length > 0)
            highestPriority = Math.Max(highestPriority, contextHandlers[0].Priority);

        return highestPriority;
    }

    /// <summary>
    ///     执行高优先级的普通事件处理器
    /// </summary>
    /// <param name="handlers">处理器数组</param>
    /// <param name="t">事件参数</param>
    /// <param name="highestPriority">最高优先级</param>
    private static void ExecuteHighPriorityNormalHandlers(EventHandler[] handlers, T t, int highestPriority)
    {
        foreach (var handler in handlers)
        {
            if (handler.Priority < highestPriority) break;
            handler.Handler.Invoke(t);
        }
    }

    /// <summary>
    ///     执行高优先级的上下文事件处理器
    /// </summary>
    /// <param name="handlers">处理器数组</param>
    /// <param name="t">事件参数</param>
    /// <param name="highestPriority">最高优先级</param>
    private static void ExecuteHighPriorityContextHandlers(ContextEventHandler[] handlers, T t, int highestPriority)
    {
        var context = new EventContext<T>(t);
        foreach (var handler in handlers)
        {
            if (handler.Priority < highestPriority) break;
            handler.Handler.Invoke(context);
        }
    }

    /// <summary>
    ///     获取当前已注册的监听器总数量（包括普通监听器和上下文监听器）
    /// </summary>
    /// <returns>监听器总数量</returns>
    public int GetListenerCount()
    {
        lock (_syncRoot)
        {
            return _handlers.Count + _contextHandlers.Count;
        }
    }

    private (EventHandler[] NormalHandlers, ContextEventHandler[] ContextHandlers) CreateSnapshots()
    {
        lock (_syncRoot)
        {
            return (_handlers.ToArray(), _contextHandlers.ToArray());
        }
    }

    /// <summary>
    ///     将普通事件处理器转换为统一的调用描述。
    /// </summary>
    /// <param name="handler">要包装的普通处理器。</param>
    /// <param name="t">当前触发的事件数据。</param>
    /// <returns>可与上下文处理器合并排序的统一调用描述。</returns>
    private static (int Priority, Action? Handler, Action<EventContext<T>>? ContextHandler, bool IsContext)
        CreateNormalHandlerInvocation(EventHandler handler, T t)
    {
        return (handler.Priority, () => handler.Handler.Invoke(t), null, false);
    }

    /// <summary>
    ///     将上下文事件处理器转换为统一的调用描述。
    /// </summary>
    /// <param name="handler">要包装的上下文处理器。</param>
    /// <returns>可与普通处理器合并排序的统一调用描述。</returns>
    private static (int Priority, Action? Handler, Action<EventContext<T>>? ContextHandler, bool IsContext)
        CreateContextHandlerInvocation(ContextEventHandler handler)
    {
        return (handler.Priority, null, handler.Handler, true);
    }

    /// <summary>
    ///     事件处理器包装类，包含处理器和优先级
    /// </summary>
    private sealed class EventHandler(Action<T> handler, int priority)
    {
        public Action<T> Handler { get; } = handler;
        public int Priority { get; } = priority;
    }

    /// <summary>
    ///     上下文事件处理器包装类，包含处理器和优先级
    /// </summary>
    private sealed class ContextEventHandler(Action<EventContext<T>> handler, int priority)
    {
        public Action<EventContext<T>> Handler { get; } = handler;
        public int Priority { get; } = priority;
    }
}
