using System;
using System.Collections.Generic;
using System.Net;
using System.Threading.Tasks;
using System.Linq;

public class ProxyManager
{
    private List<ProxyInfo> proxyPool = new List<ProxyInfo>();
    private object lockObj = new object();
    private DateTime lastResetTime = DateTime.UtcNow;
    private TimeSpan resetInterval = TimeSpan.FromHours(1); // 设置重置间隔为1小时

    public ProxyManager(IEnumerable<string> proxyAddresses)
    {
        foreach (var address in proxyAddresses)
        {
            proxyPool.Add(new ProxyInfo(new WebProxy(address)));
        }
    }

    public WebProxy GetNextProxy()
    {
        lock (lockObj)
        {
            if (DateTime.UtcNow - lastResetTime >= resetInterval) ResetCounters();
            var nextProxy = proxyPool.OrderBy(p => p.UsageCount).FirstOrDefault(p => p.IsAvailable);

            if (nextProxy != null)
            {
                nextProxy.UsageCount++;
                return nextProxy.Proxy;
            }
            return null; // 没有可用的代理时返回 null
        }
    }

    private void ResetCounters()
    {
        foreach (var proxyInfo in proxyPool)
        {
            proxyInfo.UsageCount = 0;
        }
        lastResetTime = DateTime.UtcNow;
    }

    public void ReportProxyResult(WebProxy proxy, bool isSuccess)
    {
        lock (lockObj)
        {
            var proxyInfo = proxyPool.Find(p => p.Proxy == proxy);
            if (proxyInfo != null)
            {
                if (isSuccess)
                {
                    proxyInfo.Failures = 0;
                    proxyInfo.IsAvailable = true;
                }
                else
                {
                    proxyInfo.Failures++;
                    proxyInfo.IsAvailable = false;
                    proxyInfo.LastUnavailable = DateTime.UtcNow;

                    if (proxyInfo.Failures >= 3)
                    {
                        proxyInfo.IsAvailable = false;

                        SendAlert(proxyInfo);

                        // 使用异步任务恢复代理可用状态
                        Task.Run(async () =>
                        {
                            await Task.Delay(TimeSpan.FromMinutes(1));

                            lock (lockObj)
                            {
                                // 只有在这段时间内没有再次标记为不可用时才重置代理状态
                                if (!proxyInfo.IsAvailable)
                                {
                                    proxyInfo.IsAvailable = true;
                                }
                            }
                        });
                    }
                }
            }
        }
    }

    private void SendAlert(ProxyInfo proxyInfo)
    {
        Console.WriteLine($"Alert: Proxy {proxyInfo.Proxy.Address} is repeatedly failing.");
    }
}

public class ProxyInfo
{
    public WebProxy Proxy { get; }
    public bool IsAvailable { get; set; }
    public int UsageCount { get; set; }
    public int Failures { get; set; }
    public DateTime LastUnavailable { get; set; }

    public ProxyInfo(WebProxy proxy)
    {
        Proxy = proxy;
        IsAvailable = true;
        UsageCount = 0;
        Failures = 0;
        LastUnavailable = DateTime.MinValue;
    }
}
