using Ayay.SerilogLogs;
using Serilog;

namespace SHH.CameraSdk;

/// <summary>
/// 帧控制器（混合模式最终版）
/// 策略：
/// 1. 高速直通 (> 20 FPS)：直接放行，保留硬件原始流畅度与波动。
/// 2. 低速精控 (<= 20 FPS)：使用积分算法进行精准降采样。
/// </summary>
public class FrameController
{
    private ILogger _sysLog = Log.ForContext("SourceContext", LogModules.Core);

    // 需求字典
    private readonly ConcurrentDictionary<string, FrameRequirement> _requirements = new();

    // 积分累加器（仅用于 <= 20 FPS 的精准控制）
    private readonly ConcurrentDictionary<string, int> _accumulators = new();

    private long _globalSequence = 0;

    // 逻辑基准分母：假设标准输入是 25 帧
    // 用于低帧率时的积分计算基准
    private const int LOGICAL_BASE_FPS = 25;

    // ---------------------------------------------------------
    // 注册与注销
    // ---------------------------------------------------------

    public void Register(string appId, int fps)
    {
        _requirements.AddOrUpdate(appId,
            _ => new FrameRequirement { AppId = appId, TargetFps = fps },
            (_, old) => { old.TargetFps = fps; return old; });

        // 重置该用户的积分器，确保新策略从零开始
        _accumulators.TryRemove(appId, out _);
    }

    // 修改 Register 方法，接收整个 Requirement 对象或多个参数
    public void Register(FrameRequirement req)
    {
        _requirements.AddOrUpdate(req.AppId,
            _ => req, // 如果不存在，直接添加整个对象
            (_, old) =>
            {
                // 如果已存在，更新关键业务字段，同时保留统计状态
                old.TargetFps = req.TargetFps;
                old.Memo = req.Memo;
                old.Handle = req.Handle;
                old.Type = req.Type;
                old.SavePath = req.SavePath;
                // 注意：不要覆盖 old.RealFps，保留之前的统计值
                return old;
            });

        // 如果是降频（<=20），确保积分器存在
        if (req.TargetFps <= 20)
        {
            _accumulators.GetOrAdd(req.AppId, 0);
        }
    }

    public void Unregister(string appId)
    {
        if (string.IsNullOrWhiteSpace(appId)) return;

        // 1. 从需求配置中移除
        _requirements.TryRemove(appId, out _);

        // 2. 从积分累加器中移除（防止内存泄漏）
        _accumulators.TryRemove(appId, out _);

        _sysLog.Warning($"[Core] 帧控制器已从调度中心彻底移除 AppId: {appId}");
    }

    // ---------------------------------------------------------
    // 核心决策逻辑
    // ---------------------------------------------------------

    /// <summary>
    /// 混合决策：高速直通 + 低速精控
    /// </summary>
    /// <param name="currentTick">兼容参数（内部逻辑不强依赖）</param>
    /// <param name="ignoredRealFps">兼容参数（已忽略，防止震荡）</param>
    public FrameDecision MakeDecision(long currentTick, int ignoredRealFps = 0)
    {
        var decision = new FrameDecision
        {
            Sequence = Interlocked.Increment(ref _globalSequence),
            Timestamp = DateTime.Now
        };

        foreach (var req in _requirements.Values)
        {
            if (req.TargetFps <= 0) continue;

            //// =========================================================
            //// 【策略 A】 高速直通区 (> 20 FPS)
            //// =========================================================
            //// 用户想要 21~25+ 帧，或者全速。
            //// 此时不做任何干预，相机来多少发多少，保留原始的 24-26 波动。
            //if (req.TargetFps > 20)
            //{
            //    decision.TargetAppIds.Add(req.AppId);
            //    req.LastCaptureTick = currentTick; // 更新活跃状态
            //    continue;
            //}

            // =========================================================
            // 【策略 B】 低速精控区 (<= 20 FPS) -> 积分算法
            // =========================================================
            // 解决 "16帧" 问题，保证 1帧、5帧、15帧 的绝对精准

            // 1. 获取积分
            int acc = _accumulators.GetOrAdd(req.AppId, 0);

            // 2. 累加：每来一帧，积攒 "TargetFps" 分
            acc += req.TargetFps;

            // 3. 判定：是否攒够了 25 分 (逻辑基准)
            if (acc >= LOGICAL_BASE_FPS)
            {
                // 发货
                decision.TargetAppIds.Add(req.AppId);

                // 扣除成本，保留余数 (余数是精度的关键)
                acc -= LOGICAL_BASE_FPS;

                // 【核心修复】在此处触发统计，RealFps 才会开始跳动
                req.UpdateRealFps();

                req.LastCaptureTick = currentTick;
            }

            // 4. 防爆桶机制：如果累积太多（例如相机推流极快），限制封顶
            // 防止下一秒瞬间吐出太多帧
            if (acc > LOGICAL_BASE_FPS) acc = LOGICAL_BASE_FPS;

            // 5. 写回状态
            _accumulators[req.AppId] = acc;
        }

        decision.IsCaptured = decision.TargetAppIds.Count > 0;
        return decision;
    }

    // ---------------------------------------------------------
    // 辅助状态查询
    // ---------------------------------------------------------
    public List<dynamic> GetCurrentRequirements()
    {
        return _requirements.Values.Select(r => new { r.AppId, r.TargetFps, r.RealFps, LastActive = r.LastCaptureTick, r.Memo, r.SavePath, r.Handle, r.TargetIp, r.TargetPort, r.Protocol, r.Type }).ToList<dynamic>();
    }

    // [新增] 专门供审计与管理层调用的强类型方法
    // Optimized: 避免匿名类型跨程序集访问失败，提供高性能的实体访问
    public IEnumerable<FrameRequirement> GetRequirements()
    {
        return _requirements.Values;
    }
}