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

namespace IpcLibrary.Services {
    /// <summary>
    /// 心跳管理器实现
    /// </summary>
    public class HeartbeatManager : IHeartbeatManager, IDisposable {
        private readonly ConcurrentDictionary<string, ProcessHeartbeat> _heartbeats;
        private readonly Timer _monitorTimer;
        private readonly object _lock = new object();
        private TimeSpan _heartbeatInterval = TimeSpan.FromSeconds(5);
        private TimeSpan _timeoutThreshold = TimeSpan.FromSeconds(15);
        private bool _disposed;

        public event EventHandler<string> ProcessTimeout;

        public HeartbeatManager() {
            _heartbeats = new ConcurrentDictionary<string, ProcessHeartbeat>();
            _monitorTimer = new Timer(MonitorHeartbeats, null, _heartbeatInterval, _heartbeatInterval);
        }

        public void StartMonitoring(string processId) {
            if (string.IsNullOrEmpty(processId))
                throw new ArgumentException("进程ID不能为空", nameof(processId));

            var heartbeat = new ProcessHeartbeat {
                ProcessId = processId,
                LastHeartbeat = DateTime.UtcNow,
                IsActive = true
            };

            _heartbeats.AddOrUpdate(processId, heartbeat, (key, old) => heartbeat);
        }

        public void StopMonitoring(string processId) {
            if (_heartbeats.TryGetValue(processId, out var heartbeat)) {
                heartbeat.IsActive = false;
                _heartbeats.TryRemove(processId, out _);
            }
        }

        public void UpdateHeartbeat(string processId) {
            if (_heartbeats.TryGetValue(processId, out var heartbeat)) {
                heartbeat.LastHeartbeat = DateTime.UtcNow;
            }
        }

        public void SetHeartbeatInterval(TimeSpan interval) {
            if (interval <= TimeSpan.Zero)
                throw new ArgumentException("心跳间隔必须大于零", nameof(interval));

            lock (_lock) {
                _heartbeatInterval = interval;
                _monitorTimer?.Change(interval, interval);
            }
        }

        public void SetTimeoutThreshold(TimeSpan timeout) {
            if (timeout <= TimeSpan.Zero)
                throw new ArgumentException("超时阈值必须大于零", nameof(timeout));

            _timeoutThreshold = timeout;
        }

        private void MonitorHeartbeats(object state) {
            if (_disposed)
                return;

            var now = DateTime.UtcNow;
            var timedOutProcesses = new List<string>();

            foreach (var kvp in _heartbeats) {
                var heartbeat = kvp.Value;
                if (heartbeat.IsActive && now - heartbeat.LastHeartbeat > _timeoutThreshold) {
                    timedOutProcesses.Add(kvp.Key);
                    heartbeat.IsActive = false;
                }
            }

            foreach (var processId in timedOutProcesses) {
                ProcessTimeout?.Invoke(this, processId);
            }
        }

        public void Dispose() {
            if (_disposed)
                return;

            _disposed = true;
            _monitorTimer?.Dispose();
            _heartbeats.Clear();
        }
    }
}
