using System;
using System.Collections.Generic;
using System.Linq;
using SimpleCore.Library;
using SimpleLite.RCS.CarTypes;
using StandardScene.Signal.Plc;

namespace StandardScene.Signal.Logic
{
    /// <summary>
    /// 区域车组限流。对齐反编译 <c>DefaultPlugin.RateFlowControl</c>。
    /// </summary>
    /// <remarks>
    /// 独立握手类型 <c>RateFlowControl</c> 用分号：<c>区域;车组;限额;点1,点2</c>。
    /// 挂在 JGControl 第三段时用短横：<c>区域-车组-限额-点1,点2</c>（因为前两段机构名/动作已经占用分号）。
    /// 统计「站点列表上、同车组、且不是本车」的数量，小于限额才放行。
    /// 解析异常时放行（return true），避免配错把产线卡死。
    /// </remarks>
    public static class RateFlowHandler
    {
        /// <summary>独立限流点：通过则停充并启动。</summary>
        public static void OnStopped(Car car, SignalStopSpec spec, IDictionary<string, int> logByArea)
        {
            if (AllowPass(car, spec.SignalParams, logByArea, sep: ';'))
            {
                SignalCarAdapter.StopCharge(car);
                SignalCarAdapter.Start(car);
            }
        }

        /// <summary>JGControl 第三段限流，短横分隔。不通过时调用方应直接 return，不启动。</summary>
        public static bool AllowPass(Car car, string rateFlowString, IDictionary<string, int> logByArea) =>
            AllowPass(car, rateFlowString, logByArea, sep: '-');

        /// <param name="sep">独立类型用 ';'，JGControl 挂载用 '-'。</param>
        private static bool AllowPass(Car car, string raw, IDictionary<string, int> logByArea, char sep)
        {
            try
            {
                var parts = (raw ?? "").Split(sep);
                var area = parts.Length > 0 ? parts[0] : "";
                var group = parts.Length > 1 ? parts[1] : "";
                var limit = 0;
                if (parts.Length > 2)
                    int.TryParse(parts[2], out limit);
                var sites = new List<int>();
                if (parts.Length > 3)
                {
                    foreach (var s in parts[3].Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
                    {
                        if (int.TryParse(s.Trim(), out var id))
                            sites.Add(id);
                    }
                }

                var others = SignalCarAdapter.CarsAt(sites)
                    .Where(x => x.id != car.id && string.Equals(SignalCarAdapter.GroupId(x), group, StringComparison.Ordinal))
                    .ToList();
                var count = others.Count;
                if (count < limit)
                {
                    Diagnosis.Log(
                        $"限流区域{area}限制AGV组{group}流量{limit}辆AGV，当前停放{count}，放行AGV{car.id}",
                        "RateFlow", true);
                    Note(logByArea, area, car, raw);
                    return true;
                }

                Diagnosis.Log(
                    $"限流区域{area}限制AGV组{group}流量{limit}辆AGV，当前停放{count}，无法放行",
                    "RateFlow", true);
                Note(logByArea, area, car, raw);
                return false;
            }
            catch (Exception ex)
            {
                Diagnosis.Log($"处理区域限流业务异常：{ex.Message}", "RateFlow", true);
                return true;
            }
        }

        /// <summary>同一限流区域仅在「决策车号变化」时再打一条带原始参数的日志。</summary>
        private static void Note(IDictionary<string, int> logByArea, string area, Car car, string raw)
        {
            if (logByArea == null) return;
            var changed = !logByArea.TryGetValue(area, out var last) || last != car.id;
            logByArea[area] = car.id;
            if (changed)
                Diagnosis.Log($"AGV{car.id}停在地标{SignalCarAdapter.PositionId(car)}，配置参数：【{raw}】", "RateFlow", true);
        }
    }
}
