using System;
using System.IO;
using System.Threading;
using LessokajiWeaverUtilities.Utilities;
using Newtonsoft.Json;
using SimpleCore;
using SimpleCore.Library;
using SimpleLite.RCS;
using StandardScene.Signal.Logic;
using StandardScene.Signal.Model;
using StandardScene.Signal.Ui;
using StandardScene.Utils;

namespace StandardScene.Signal
{
    /// <summary>
    /// 磁条交管进程：只针对 MagCar。同区名排队后，按「本线 + 冲突对向线」站点并集查占用，容量允许则发启动。
    /// </summary>
    /// <remarks>
    /// 配置 <c>Config/Signal/mag-control-areas.json</c>。
    /// 同「管控区名称」绑成一个路口排队；放行时合并本线与冲突对向线的管控站点列表统计当前占用。
    /// 不使用 pending 在途占额。不处理 Mag2Car。
    /// </remarks>
    [MissionType(Name = "磁条交管进程", editor = typeof(MagTrafficMission))]
    [I18N.DocumentTranslation(Name = "Magnetic Traffic Mission", locale = "en")]
    public class MagTrafficMission : Mission
    {
        /// <summary>扫车周期（毫秒）。停在触发点的 MagCar 每拍排队判定一次。</summary>
        [FieldMember] public int TickMs = 1000;

        /// <summary>管控区表路径。相对路径只解析工作目录 <c>Config/Signal</c>。</summary>
        [FieldMember] public string AreasPath = @"Config\Signal\mag-control-areas.json";

        /// <summary>放行日志根目录。实际按车名落在其下 mag-traffic/car{name}/release_yyyyMMdd.log。</summary>
        [FieldMember] public string LogDirectory = "log";

        /// <summary>是否把交管放行写入本地文件留档。</summary>
        [FieldMember] public bool EnableFileLog = true;

        [JsonIgnore] private bool _started;
        [JsonIgnore] private readonly MagControlRuntime _runtime = new MagControlRuntime();
        [JsonIgnore] private CancellationTokenSource _cts;
        [JsonIgnore] private Thread _thread;

        public class MagTrafficMissionStatus : MissionStatus
        {
            public int RuleCount { get; set; }
            public int WaitingAtTrigger { get; set; }
            public int PendingInFlight { get; set; }
            public int ScanTickCount { get; set; }
            public string AreasFile { get; set; }
        }

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

        public static Mission Create() => new MagTrafficMission();

        [MethodMember(Name = "启动进程", Description = "加载管控区表，按区名排队后对 MagCar 发放行")]
        public override void Execute()
        {
            try
            {
                MagTrafficFileLogger.Configure(LogDirectory, EnableFileLog);
                ReloadConfig();
                _started = true;
                StartWatch();
                MagTrafficFileLogger.WriteSystem($"进程启动 规则={((MagTrafficMissionStatus)status).RuleCount} 配置={((MagTrafficMissionStatus)status).AreasFile}");
                Diagnosis.Post(
                    $"磁条交管进程已启动，规则={((MagTrafficMissionStatus)status).RuleCount}（仅 MagCar），放行日志={MagTrafficFileLogger.GetLogDirectory()}",
                    "MagTraffic", true);
            }
            catch (Exception ex)
            {
                status.status = "启动失败";
                Diagnosis.Post($"磁条交管进程启动失败：{ExceptionFormatter.FormatEx(ex)}", "MagTraffic", true);
                throw;
            }
        }

        [MethodMember(Name = "重新加载配置", Description = "重新读取 mag-control-areas.json")]
        public void ReloadConfig()
        {
            var file = SignalConfigStore.Resolve(AreasPath);
            var rows = SignalConfigStore.Load<MagControlAreaModel>(file);
            _runtime.Replace(rows);

            var st = (MagTrafficMissionStatus)status;
            st.AreasFile = file;
            st.RuleCount = _runtime.RuleCount;
            st.PendingInFlight = _runtime.PendingCount;
            status.status = _started ? "运行中" : "配置已加载";
            MagTrafficFileLogger.Configure(LogDirectory, EnableFileLog);
            MagTrafficFileLogger.WriteSystem($"重新加载配置 规则={st.RuleCount} 文件={file}");
            Diagnosis.Post($"磁条交管配置已加载：启用规则 {st.RuleCount} @ {file}", "MagTraffic", true);
        }

        [MethodMember(Name = "停止进程")]
        public new void Stop()
        {
            _started = false;
            StopWatch();
            status.status = "已停止";
            MagTrafficFileLogger.WriteSystem("进程停止");
            Diagnosis.Post("磁条交管进程已停止", "MagTraffic", true);
        }

        [MethodMember(Name = "打开放行日志目录", Description = "打开 mag-traffic 目录（按 car{name} 分子目录），便于按车查阅放行记录")]
        public void OpenReleaseLogFolder()
        {
            try
            {
                MagTrafficFileLogger.Configure(LogDirectory, EnableFileLog);
                var dir = MagTrafficFileLogger.GetLogDirectory();
                Directory.CreateDirectory(dir);
                System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo
                {
                    FileName = dir,
                    UseShellExecute = true
                });
            }
            catch (Exception ex)
            {
                CycleUiHelper.Alert("错误", $"打开放行日志目录失败：{ex.Message}");
            }
        }

        [MethodMember(Name = "打开管控区列表", Description = "编辑区名 / 兼容组 / 优先级 / 等待时长 / 触发点 / 区内站点 / 容量")]
        public void OpenAreas()
        {
            try
            {
                var path = SignalConfigStore.Resolve(AreasPath);
                ModelListPanel<MagControlAreaModel>.Open(
                    "磁条管控区配置",
                    path,
                    x => x == null ? "" : x.TriggerSit.ToString());
            }
            catch (Exception ex)
            {
                CycleUiHelper.Alert("错误", $"打开管控区列表失败：{ex.Message}");
            }
        }

        private void StartWatch()
        {
            StopWatch();
            _cts = new CancellationTokenSource();
            _thread = new Thread(WatchLoop)
            {
                IsBackground = true,
                Name = "MagTrafficWatch"
            };
            _thread.Start();
        }

        private void StopWatch()
        {
            try { _cts?.Cancel(); }
            catch { }
            try { _thread?.Join(2000); }
            catch { }
            _thread = null;
        }

        private void WatchLoop()
        {
            var token = _cts.Token;
            var tick = 0;
            var interval = Math.Max(200, TickMs);
            while (!token.IsCancellationRequested)
            {
                try
                {
                    var (waiting, _) = _runtime.ScanAndRelease();
                    var st = (MagTrafficMissionStatus)status;
                    st.WaitingAtTrigger = waiting;
                    st.PendingInFlight = _runtime.PendingCount;
                    st.RuleCount = _runtime.RuleCount;
                    st.ScanTickCount = ++tick;
                    if (_started)
                        status.status = $"运行中 规则{st.RuleCount} 等待{waiting}";
                }
                catch (Exception ex)
                {
                    Diagnosis.Log($"磁条交管扫车异常：{ex.Message}", "MagTraffic", true);
                }

                try { Thread.Sleep(interval); }
                catch (ThreadInterruptedException) { break; }
            }
        }
    }
}
