using dodohold.core;
using molilian.core;
using Org.BouncyCastle.Crypto;
using System;
using System.Collections.Concurrent;
using System.Linq;
using YunhuiKit;
using static molilian.core.TkPoolCore;

public partial class TkEndpointCore
{
    private static SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1);

    private static IEnumerable<TkEndpointConfigDTO> _cached;

    // 添加到 TkEndpointCore 类中
    private static readonly ConcurrentDictionary<(int, bool?, string), List<TkEndpointConfigDTO>> _accountEndpointCache = new();


    private static async Task<IEnumerable<TkEndpointConfigDTO>> ListAsync(bool force = false)
    {
        // 内存缓存检查
        if (!force && _cached != null) return _cached;
        string cache_key = "cache:tk_endpoint_config";

        if (!force)
        {
            var cachedList = await RedisHelper.GetAsync<IEnumerable<TkEndpointConfigDTO>>(cache_key);
            if (cachedList != null)
            {
                _cached = cachedList;
                return cachedList;
            }
        }
        // 获取新数据
        await _semaphore.WaitAsync();
        try
        {
            // 双重检查，防止并发情况下重复加载
            if (!force)
            {
                var cachedList = await RedisHelper.GetAsync<IEnumerable<TkEndpointConfigDTO>>(cache_key);
                if (cachedList != null)
                {
                    _cached = cachedList;
                    return cachedList;
                }
            }

            // 从数据库加载数据
            var list = new DBContext.Table("tk_endpoint_config")
                .Where("status=@status", new { status = 1 })
                .Select<TkEndpointConfigDTO>();

            if (list == null) return default;

            // 更新调用次数
            //foreach (var item in list)
            //{
            //    item.current_daily_calls = await RiskControlCore.GetAllNodesTkEndpointCallsAsync(item.id, DateTime.Now.ToString("yyyyMMdd"));
            //    item.current_hourly_calls = await RiskControlCore.GetAllNodesTkEndpointCallsAsync(item.id, DateTime.Now.ToString("yyyyMMddHH"));
            //}

            // 更新缓存
            await RedisHelper.SetAsync(cache_key, list, 30 * 86400);
            _cached = list;
            _accountEndpointCache.Clear();
            return list;
        }
        finally
        {
            _semaphore.Release();
        }
    }


    public static Task<List<TkEndpointConfigDTO>> GetEndpointsByAccountAsync(int accountId, bool? isTaobaoUrl = null, string parseEndpoints = null)
    {
        return GetEndpointsByAccountInternalAsync(accountId, isTaobaoUrl, parseEndpoints, cloneResult: true);
    }

    public static Task<List<TkEndpointConfigDTO>> GetEndpointsByAccountReadonlyAsync(int accountId, bool? isTaobaoUrl = null, string parseEndpoints = null)
    {
        return GetEndpointsByAccountInternalAsync(accountId, isTaobaoUrl, parseEndpoints, cloneResult: false);
    }

    private static async Task<List<TkEndpointConfigDTO>> GetEndpointsByAccountInternalAsync(int accountId, bool? isTaobaoUrl, string parseEndpoints, bool cloneResult)
    {
        string normalizedParseEndpoints = NormalizeParseEndpoints(parseEndpoints);
        var cacheKey = (accountId, isTaobaoUrl, normalizedParseEndpoints);

        if (_accountEndpointCache.TryGetValue(cacheKey, out var cached))
            return cloneResult ? cached.Select(x => x.DeepCopy()).ToList() : cached;

        // 2. 获取所有端点（包含全局和专属）
        var allEndpoints = (await ListAsync())?.Where(e => e.status).ToList() ?? [];

        // 3. 合并逻辑：专属配置覆盖全局配置（关键！）
        var mergedEndpoints = allEndpoints
            .GroupBy(e => e.endpoint)
            .Select(g =>
            {
                // 优先取专属配置
                var accountSpecific = g.FirstOrDefault(e => e.tk_pool_id == accountId);
                if (accountSpecific != null)
                    return accountSpecific.DeepCopy(); // 深拷贝专属配置

                // 否则取全局配置（tk_pool_id=0）
                var global = g.FirstOrDefault(e => e.tk_pool_id == 0);
                return global?.DeepCopy(); // 深拷贝全局配置
            })
            .Where(e => e != null)
            .ToList();

        // 4. 根据isTaobaoUrl过滤
        if (isTaobaoUrl.HasValue)
        {
            mergedEndpoints = mergedEndpoints.Where(e =>
            {
                if (e.taobao_id_handling == 0) return true;
                if (e.taobao_id_handling == 1 && isTaobaoUrl.Value) return true;
                if (e.taobao_id_handling == 2 && !isTaobaoUrl.Value) return true;
                return false;
            }).ToList();
        }

        // 5. 排除指定的端点
        if (!string.IsNullOrEmpty(normalizedParseEndpoints))
        {
            var parseEndpointIds = normalizedParseEndpoints.Split(',')
                .Select(idStr => int.TryParse(idStr.Trim(), out var id) ? id : (int?)null)
                .Where(id => id.HasValue)
                .Select(id => id.Value)
                .ToHashSet();

            mergedEndpoints = mergedEndpoints.Where(e => parseEndpointIds.Contains(e.ep_id)).ToList();
        }

        // 6. 存入缓存
        var cachedValue = mergedEndpoints.Select(x => x.DeepCopy()).ToList();
        _accountEndpointCache.TryAdd(cacheKey, cachedValue);
        return cloneResult ? cachedValue.Select(x => x.DeepCopy()).ToList() : cachedValue;
    }



    // 添加缓存清理方法
    public static void ClearEndpointCache(int accountId)
    {
        foreach (var key in _accountEndpointCache.Keys.Where(key => key.Item1 == accountId).ToList())
        {
            _accountEndpointCache.TryRemove(key, out _);
        }
    }



    public static void Refresh()
    {
        _ = AllListAsync(true);
        _ = ListAsync(true);
        _accountEndpointCache.Clear();
    }

    private static string NormalizeParseEndpoints(string? parseEndpoints)
    {
        if (string.IsNullOrWhiteSpace(parseEndpoints)) return string.Empty;

        return string.Join(",",
            parseEndpoints.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
                .Where(item => !string.IsNullOrWhiteSpace(item))
                .Distinct(StringComparer.Ordinal)
                .OrderBy(item => item, StringComparer.Ordinal));
    }

}
