using LessokajiWeaverUtilities.Utilities;
using Newtonsoft.Json;
using Simple3.RCS;
using Simple3.Props;
using SimpleCore;
using SimpleCore.Library;
using SimpleCore.PropType;
using StandardScene;
using StandardScene.Scheduler.FassEvent;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Simple3.RCS.CarTypes;


namespace StandardScene.Scheduler
{
    /// <summary>
    /// FASS 车辆事件调度进程。
    /// <para>
    /// 移植自 <c>fass/FASS.Scheduler/Services/Events/EventCarService.cs</c>：
    /// 按 JSON 配置定时轮询全场车辆，匹配触发条件后执行交管/PLC/电量等条件判断，
    /// 最终对 MagCar 下发 Start（放行）或 Stop（停车）。
    /// </para>
    /// <para>
    /// 使用方式：在场景中添加本 Mission →「启动进程」→ 默认加载 <c>Configs\EventCar\FG2512073.json</c>。
    /// </para>
    /// </summary>
    [MissionType(Name = "FASS车辆事件进程", editor = typeof(EventCarMission))]
    [I18N.DocumentTranslation(Name = "FASS Event Car Mission", locale = "en")]
    public class EventCarMission : Mission
    {
        /// <summary>EventCar JSON 配置文件路径（相对程序目录或绝对路径）。</summary>
        [FieldMember] public string EventConfigPath = "Config\\EventCar\\traffic.json";

        /// <summary>主循环轮询间隔（毫秒），对应 FASS TimerTick 频率，默认 500ms。</summary>
        [FieldMember] public int TickIntervalMs = 500;

        /// <summary>与下料站/安全信号交互用的西门子 PLC IP。</summary>
        [FieldMember] public string PlcIpAddress = "127.0.0.1";

        /// <summary>PLC 端口，S7 默认 102。</summary>
        [FieldMember] public int PlcPort = 102;

        /// <summary>PLC 型号字符串，如 S7_1500、S7_300，传给 IoTClient SiemensClient。</summary>
        [FieldMember] public string PlcVersion = "S7_1500";

        /// <summary>是否启用 ME11 下料站 PLC 信号交互（false 时 requestStaion/InplaceStaion 等直接返回 true）。</summary>
        [FieldMember] public bool IsEnableMEll = true;


        /// <summary>充电完成放行默认电量阈值（%），可被事件内 ChargeStart 参数覆盖。</summary>
        [FieldMember] public double ChargeStartThreshold = 93;


        [JsonIgnore] private bool _started;

        [JsonIgnore] private Thread _workerThread;

        [JsonIgnore] private FassEventCarHandler _handler;

        /// <summary>当前生效的车辆事件配置列表（TriggerSource=Car 且 TriggerEnable=true）。</summary>
        [JsonIgnore] private List<FassEventCarConfig> _eventCars = new List<FassEventCarConfig>();

        /// <summary>记录每辆车上一周期的 CurrentNode，用于 PrevNode 触发与地标变化时清除任务防重复标记。</summary>
        [JsonIgnore] private readonly Dictionary<int, string> _prevNodeByCarId = new Dictionary<int, string>();

        /// <summary>每车最多一个在飞 Tick，避免断网重试把 Task.Run 堆爆、同一车并发下发。</summary>
        [JsonIgnore] private readonly ConcurrentDictionary<int, byte> _tickInFlight = new ConcurrentDictionary<int, byte>();

        /// <summary>进程运行状态扩展字段。</summary>
        public class EventCarMissionStatus : MissionStatus
        {
            /// <summary>主循环已执行次数。</summary>
            public int TickCount { get; set; }

            /// <summary>已加载的事件规则条数。</summary>
            public int LoadedEventCount { get; set; }

            /// <summary>实际加载的配置文件绝对/解析路径。</summary>
            public string ConfigPath { get; set; }
        }

        public override MissionStatus status { get; set; } = new EventCarMissionStatus();

        public static Mission Create()
        {
            return new EventCarMission();
        }

        /// <summary>
        /// 启动后台轮询线程：加载配置 → 创建 Handler → 周期性 ProcessAllCars。
        /// </summary>
        [MethodMember(Name = "启动进程", Description = "加载 FASS EventCar 配置并开始轮询车辆事件")]
        public override void Execute()
        {
            if (_started)
            {
                status.status = "已在运行";
                return;
            }

            try
            {
                ReloadConfig();
            }
            catch (Exception ex)
            {
                status.status = "配置加载失败";
                Diagnosis.Post($"FASS车辆事件进程配置加载失败：{ExceptionFormatter.FormatEx(ex)}", "FassEventCar", true);
                throw;
            }

            _handler = new FassEventCarHandler(this);
            _started = true;
            status.status = "运行中";

            _workerThread = new Thread(WorkerLoop)
            {
                IsBackground = true,
                Name = "EventCarMission"
            };
            _workerThread.Start();
            Diagnosis.Post($"FASS车辆事件进程已启动，配置数={_eventCars.Count}", "FassEventCar", true);
        }

        /// <summary>热加载 JSON 配置，运行中也可调用。</summary>
        [MethodMember(Name = "重新加载配置", Description = "重新读取 EventCar JSON 配置")]
        public void ReloadConfig()
        {
            var path = ResolveConfigPath();
            _eventCars = FassEventConfigLoader.Load(path)
                .Where(item => item.TriggerEnable && string.Equals(item.TriggerSource, "Car", StringComparison.OrdinalIgnoreCase))
                .ToList();

            var missionStatus = (EventCarMissionStatus)status;
            missionStatus.LoadedEventCount = _eventCars.Count;
            missionStatus.ConfigPath = path;
            status.status = _started ? "运行中" : "配置已加载";
            Diagnosis.Post($"FASS EventCar 配置已加载：{path}，事件数={_eventCars.Count}", "FassEventCar", true);
        }

        /// <summary>停止轮询并等待工作线程结束（最多 2 秒）。覆盖基类 Stop，避免全量重载后线程仍在对全场车下发。</summary>
        [MethodMember(Name = "停止进程", Description = "停止 FASS 车辆事件轮询")]
        public override void Stop()
        {
            _started = false;
            try
            {
                _workerThread?.Join(2000);
            }
            catch
            {
            }

            _workerThread = null;
            Diagnosis.Post("FASS车辆事件进程已停止", "FassEventCar", true);
            base.Stop();
            status.status = "已停止";
        }

        /// <summary>
        /// 后台主循环：每 TickIntervalMs 扫描一次全场车辆。
        /// 单轮异常不会终止进程，仅写诊断日志。
        /// </summary>
        private void WorkerLoop()
        {
            while (_started)
            {
                try
                {
                    ProcessAllCars();
                    var missionStatus = (EventCarMissionStatus)status;
                    missionStatus.TickCount++;
                    status.status = $"运行中:{missionStatus.TickCount}";
                }
                catch (Exception ex)
                {
                    Diagnosis.Post($"FASS车辆事件进程循环异常：{ExceptionFormatter.FormatEx(ex)}", "FassEventCar", true);
                }

                Thread.Sleep(Math.Max(100, TickIntervalMs));
            }
        }

        /// <summary>
        /// 遍历所有 Car，构建快照后 Task.Run 处理：一车断网不堵其它车。
        /// 同一车上一拍未结束则跳过本拍，禁止无界堆积。
        /// </summary>
        private void ProcessAllCars()
        {
            var handler = _handler;
            var eventCars = _eventCars;
            if (handler == null || eventCars == null)
            {
                return;
            }

            foreach (var car in SimpleLib.GetAllCars().OfType<Car>())
            {
                if (car.status == null)
                {
                    continue;
                }

                var usage = car.status.usage?.Get();
                if (usage != null && usage.refreshing == false)
                {
                    continue;
                }

                var currentNode = FassEventCarSnapshotFactory.GetCurrentNodeCode(car);
                _prevNodeByCarId.TryGetValue(car.id, out var prevNode);
                var snapshot = FassEventCarSnapshotFactory.Create(car, prevNode, FassEventCarSnapshotFactory.GetNextNodeCode(car));

                if (!string.Equals(prevNode, currentNode, StringComparison.OrdinalIgnoreCase))
                {
                    _prevNodeByCarId[car.id] = currentNode;
                    ClearTaskTags(car);
                }

                if (!_tickInFlight.TryAdd(car.id, 0))
                {
                    continue;
                }

                var carId = car.id;
                Task.Run(() =>
                {
                    try
                    {
                        if (_started)
                            handler.HandleCarTimerTick(car, snapshot, eventCars);
                    }
                    catch (Exception ex)
                    {
                        Diagnosis.Post(
                            $"FASS车辆事件处理异常 car={carId}：{ExceptionFormatter.FormatEx(ex)}",
                            "FassEventCar",
                            true);
                    }
                    finally
                    {
                        _tickInFlight.TryRemove(carId, out _);
                    }
                });
            }
        }

        /// <summary>车辆换地标后删除防重复执行标签，使同一规则可在新站点再次触发。</summary>
        private static void ClearTaskTags(Car car)
        {
            if (car.tags == null)
            {
                return;
            }

            Commons.DeleteTag(car.tags, FassEventCarHandler.ActiveTaskTag);
        }

        /// <summary>
        /// 解析配置文件路径：绝对路径直接用；相对路径依次尝试 BaseDirectory、CurrentDirectory、上级目录。
        /// </summary>
        private string ResolveConfigPath()
        {
            if (Path.IsPathRooted(EventConfigPath))
            {
                return EventConfigPath;
            }

            var candidates = new[]
            {
                Path.Combine(AppDomain.CurrentDomain.BaseDirectory, EventConfigPath),
                Path.Combine(Directory.GetCurrentDirectory(), EventConfigPath),
                Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "..", EventConfigPath))
            };

            return candidates.FirstOrDefault(File.Exists) ?? candidates[0];
        }
    }
}
