using IpcLibrary.Core;
using IpcLibrary.Core.Exceptions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace IpcLibrary.Server {
    /// <summary>
    /// 服务器扩展方法
    /// </summary>
    public static class IPCServerExtensions {
        /// <summary>
        /// 调用无返回值的方法
        /// </summary>
        public static async Task CallMethodAsync(this IIPCServer server, string targetProcessId, string serviceName, string methodName, params object[] parameters) {
            await server.CallMethodAsync<object>(targetProcessId, serviceName, methodName, parameters);
        }

        /// <summary>
        /// 注册多个服务
        /// </summary>
        public static async Task RegisterServicesAsync(this IIPCServer server, Dictionary<string, object> services) {
            foreach (var kvp in services) {
                await server.RegisterServiceAsync(kvp.Key, kvp.Value);
            }
        }

        /// <summary>
        /// 获取在线进程数量
        /// </summary>
        public static int GetOnlineProcessCount(this IIPCServer server) {
            return server.ConnectedProcesses.Count(p => p.Status == ProcessStatus.Connected);
        }

        /// <summary>
        /// 获取指定状态的进程
        /// </summary>
        public static IEnumerable<ProcessInfo> GetProcessesByStatus(this IIPCServer server, ProcessStatus status) {
            return server.ConnectedProcesses.Where(p => p.Status == status);
        }

        /// <summary>
        /// 向指定状态的所有进程发送通知
        /// </summary>
        public static async Task BroadcastToStatusAsync(this IIPCServer server, ProcessStatus status, string method, params object[] parameters) {
            var processes = server.GetProcessesByStatus(status);
            var tasks = processes.Select(p => server.SendNotificationAsync(p.ProcessId, method, parameters));
            await Task.WhenAll(tasks);
        }

        /// <summary>
        /// 使用重试机制调用方法
        /// </summary>
        public static async Task<T> CallMethodWithRetryAsync<T>(this IIPCServer server, string targetProcessId, string serviceName, string methodName, int maxRetries = 3, TimeSpan? retryDelay = null, params object[] parameters) {
            var delay = retryDelay ?? TimeSpan.FromSeconds(1);
            Exception lastException = null;

            for (int attempt = 0; attempt <= maxRetries; attempt++) {
                try {
                    return await server.CallMethodAsync<T>(targetProcessId, serviceName, methodName, parameters);
                } catch (Exception ex) {
                    lastException = ex;

                    if (attempt < maxRetries) {
                        await Task.Delay(delay);
                    }
                }
            }

            throw new MethodCallException($"方法调用在 {maxRetries + 1} 次尝试后仍然失败", lastException);
        }

        /// <summary>
        /// 等待指定数量的进程连接
        /// </summary>
        public static async Task<bool> WaitForProcessesAsync(this IIPCServer server, int expectedCount, TimeSpan timeout) {
            var startTime = DateTime.UtcNow;

            while (DateTime.UtcNow - startTime < timeout) {
                if (server.GetOnlineProcessCount() >= expectedCount) {
                    return true;
                }

                await Task.Delay(100);
            }

            return false;
        }
    }

}
