using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using LessokajiWeaverUtilities.MagicAttributes;
using LessokajiWeaverUtilities.Utilities;
using Simple3;
using Simple3.RCS;
using Simple3.RCS.CarTypes;
using SimpleCore;
using SimpleCore.Library;
using StandardScene;
using StandardScene.Utils;

namespace StandardScene.ExtendDevice.ButtonBox
{
    [MissionType(Name = "按钮进程")]
    [I18N.DocumentTranslation(Name = "ButtonMission",locale = "en")]
    public class ButtonMission:Mission
    {
        private const string DataFileName = "ButtonBoxConfig.json";
        private string _dataFilePath;
        
        /// <summary>
        /// 当前所有按钮盒实例列表
        /// </summary>
        private List<BasicButtonBox> _buttonBoxes = new List<BasicButtonBox>();
        
        /// <summary>
        /// 用于管理异步循环的取消令牌源
        /// </summary>
        private CancellationTokenSource _cancellationTokenSource;

        /// <summary>
        /// 保存监控配置与状态的后台任务，便于关闭时等待
        /// </summary>
        private Task _configTask;

        private Task _stateTask;
        
        /// <summary>
        /// 同步锁，用于保护按钮盒列表的并发访问
        /// </summary>
        private readonly object _syncLock = new object();

        [MethodMember(Name = "启动进程")]
        [I18N.DocumentTranslation(Name = "Start Mission", locale = "en")]
        public override void Execute()
        {
            // 设置数据文件路径
            _dataFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, DataFileName);
            
            // 如果已经启动，先停止之前的循环
            StopInternalAsync().GetAwaiter().GetResult();
            
            // 创建新的取消令牌源
            _cancellationTokenSource = new CancellationTokenSource();
            
            // 启动异步循环
            var token = _cancellationTokenSource.Token;
            _configTask = Task.Run(async () => await MonitorButtonBoxConfigAsync(token), token);
            _stateTask = Task.Run(async () => await MonitorButtonStatesAsync(token), token);
            status.status = "Running";
        }

        /// <summary>
        /// 异步监控按钮盒配置文件
        /// </summary>
        private async Task MonitorButtonBoxConfigAsync(CancellationToken cancellationToken)
        {
            while (!cancellationToken.IsCancellationRequested)
            {
                try
                {
                    // 读取配置文件
                    var configButtonBoxes = LoadButtonBoxConfig();
                    
                    // 同步按钮盒列表
                    SyncButtonBoxes(configButtonBoxes);
                    
                    // 等待10秒
                    await Task.Delay(TimeSpan.FromSeconds(10), cancellationToken);
                }
                catch (OperationCanceledException)
                {
                    // 正常取消，退出循环
                    break;
                }
                catch (Exception ex)
                {
                    // 记录错误，但继续运行
                    Diagnosis.Log($"按钮盒配置监控错误: {ExceptionFormatter.FormatEx(ex)}", "ButtonMission", true);
                    // 发生错误时等待5秒后重试
                    try
                    {
                        await Task.Delay(TimeSpan.FromSeconds(5), cancellationToken);
                    }
                    catch (OperationCanceledException)
                    {
                        break;
                    }
                }
            }
        }

        /// <summary>
        /// 停止监控任务
        /// </summary>
        [MethodMember(Name = "停止进程")]
        [I18N.DocumentTranslation(Name = "Stop Mission", locale = "en")]
        public override void Stop()
        {
            StopInternalAsync().GetAwaiter().GetResult();
            status.status = "/";
        }

        /// <summary>
        /// 取消并释放当前的取消令牌源
        /// </summary>
        private async Task StopInternalAsync()
        {
            var cts = Interlocked.Exchange(ref _cancellationTokenSource, null);
            var configTask = Interlocked.Exchange(ref _configTask, null);
            var stateTask = Interlocked.Exchange(ref _stateTask, null);

            if (cts == null && configTask == null && stateTask == null)
            {
                return;
            }

            try
            {
                cts?.Cancel();
            }
            catch (ObjectDisposedException)
            {
                // 已释放，忽略
            }

            var runningTasks = new[] { configTask, stateTask }
                .Where(t => t != null)
                .ToArray();

            if (runningTasks.Length > 0)
            {
                var aggregateTask = Task.WhenAll(runningTasks);
                var timeoutTask = Task.Delay(TimeSpan.FromSeconds(5));
                var completedTask = await Task.WhenAny(aggregateTask, timeoutTask).ConfigureAwait(false);

                if (completedTask == timeoutTask)
                {
                    Diagnosis.Log("停止按钮监控任务超时", "ButtonMission", true);
                }
                else
                {
                    try
                    {
                        await aggregateTask.ConfigureAwait(false);
                    }
                    catch (Exception ex)
                    {
                        Diagnosis.Log($"停止按钮监控任务时发生异常: {ExceptionFormatter.FormatEx(ex)}", "ButtonMission", true);
                    }
                }
            }

            cts?.Dispose();

            DisconnectAllButtonBoxes();
        }

        /// <summary>
        /// 断开所有按钮盒连接
        /// </summary>
        private void DisconnectAllButtonBoxes()
        {
            List<BasicButtonBox> snapshot;
            lock (_syncLock)
            {
                snapshot = _buttonBoxes.ToList();
            }

            foreach (var box in snapshot)
            {
                try
                {
                    box.Disconnect();
                }
                catch (Exception ex)
                {
                    Diagnosis.Log($"停止按钮盒失败: Index={box.Index}, Error={ExceptionFormatter.FormatEx(ex)}", "ButtonMission", true);
                }
            }
        }

        /// <summary>
        /// 监控按钮状态，用于触发按钮动作
        /// </summary>
        private async Task MonitorButtonStatesAsync(CancellationToken cancellationToken)
        {
            while (!cancellationToken.IsCancellationRequested)
            {
                try
                {
                    List<(BasicButtonBox Box, ButtonModel Config)> snapshot;
                    lock (_syncLock)
                    {
                        snapshot = _buttonBoxes
                            .SelectMany(box => box.ButtonConfigs.Values.Select(cfg => (Box: box, Config: cfg)))
                            .ToList();
                    }

                    foreach (var (box, config) in snapshot)
                    {
                        if (box == null || config == null)
                        {
                            continue;
                        }

                        if (string.IsNullOrWhiteSpace(config.TriggerMission) ||
                         string.IsNullOrWhiteSpace(config.TriggerMethod))
                        {
                            continue;
                        }
                        var desiredState = ButtonState.Pressed;
                        if (!string.IsNullOrWhiteSpace(config.TriggerState) &&
                            Enum.TryParse(config.TriggerState, out ButtonState parsedState))
                        {
                            desiredState = parsedState;
                        }

                        var currentState = box.GetButtonState(config.Index);
                        bool isActive = currentState == desiredState&&box.IsOnline;

                        int delay = config.TriggerDelay;
                        if (delay <= 0)
                        {
                            delay = 1;
                        }

                        int uniqueId = unchecked((box.Index << 16) ^ config.Index);

                        LadderLogic.TriggerOnce(isActive, delay*1000, () =>
                        {
                            ExecuteButtonAction(config, box);
                        }, uniqueId);
                    }
                }
                catch (OperationCanceledException)
                {
                    break;
                }
                catch (Exception ex)
                {
                    Diagnosis.Log($"按钮状态监控错误: {ExceptionFormatter.FormatEx(ex)}", "ButtonMission", true);
                }

                try
                {
                    await Task.Delay(TimeSpan.FromMilliseconds(500), cancellationToken);
                }
                catch (OperationCanceledException)
                {
                    break;
                }
            }
        }

        /// <summary>
        /// 加载按钮盒配置文件
        /// </summary>
        private List<ButtonBoxModel> LoadButtonBoxConfig()
        {
            try
            {
                if (File.Exists(_dataFilePath))
                {
                    var jsonContent = File.ReadAllText(_dataFilePath, Encoding.UTF8);
                    if (!string.IsNullOrWhiteSpace(jsonContent))
                    {
                        var buttonBoxes = jsonContent.JsonTo<List<ButtonBoxModel>>();
                        return buttonBoxes ?? new List<ButtonBoxModel>();
                    }
                }
            }
            catch (Exception ex)
            {
                Diagnosis.Log($"加载按钮盒配置文件失败: {ExceptionFormatter.FormatEx(ex)}", "ButtonMission", true);
            }
            
            return new List<ButtonBoxModel>();
        }

        /// <summary>
        /// 同步按钮盒列表，根据配置文件进行增删改
        /// </summary>
        private void SyncButtonBoxes(List<ButtonBoxModel> configButtonBoxes)
        {
            var boxesToAdd = new List<ButtonBoxModel>();

            lock (_syncLock)
            {
                // 创建配置中的按钮盒索引字典，用于快速查找
                var configDict = configButtonBoxes.ToDictionary(b => b.Index);
                
                // 创建当前按钮盒索引字典
                var currentDict = _buttonBoxes.ToDictionary(b => b.Index);
                
                // 1. 删除：在配置中不存在的按钮盒
                var toRemove = _buttonBoxes.Where(b => !configDict.ContainsKey(b.Index)).ToList();
                foreach (var buttonBox in toRemove)
                {
                    try
                    {
                        // 断开连接
                        buttonBox.Disconnect();
                        _buttonBoxes.Remove(buttonBox);
                        Diagnosis.Post($"删除按钮盒: Index={buttonBox.Index}, IP={buttonBox.Ip}", "ButtonMission", true);
                    }
                    catch (Exception ex)
                    {
                        Diagnosis.Log($"删除按钮盒失败: {ExceptionFormatter.FormatEx(ex)}", "ButtonMission", true);
                    }
                }
                
                // 2. 添加和修改：遍历配置中的按钮盒
                foreach (var configBox in configButtonBoxes)
                {
                    if (currentDict.TryGetValue(configBox.Index, out var existingBox))
                    {
                        // 修改：检查是否需要更新
                        if (ShouldUpdateButtonBox(existingBox, configBox))
                        {
                            try
                            {
                                UpdateButtonBox(existingBox, configBox);
                                Diagnosis.Post($"更新按钮盒: Index={configBox.Index}, IP={configBox.Ip}, Type={configBox.Type}", "ButtonMission", true);
                            }
                            catch (Exception ex)
                            {
                                Diagnosis.Log($"更新按钮盒失败: {ExceptionFormatter.FormatEx(ex)}", "ButtonMission", true);
                            }
                        }
                    }
                    else
                    {
                        boxesToAdd.Add(configBox);
                    }
                }
            }

            foreach (var configBox in boxesToAdd)
            {
                try
                {
                    var newBox = CreateButtonBoxInstance(configBox);
                    if (newBox != null)
                    {
                        lock (_syncLock)
                        {
                            _buttonBoxes.Add(newBox);
                        }
                        Diagnosis.Post($"添加按钮盒: Index={configBox.Index}, IP={configBox.Ip}, Type={configBox.Type}", "ButtonMission", true);
                    }
                    else
                    {
                        Diagnosis.Log($"无法创建按钮盒实例: Index={configBox.Index}, Type={configBox.Type}", "ButtonMission", true);
                    }
                }
                catch (Exception ex)
                {
                    Diagnosis.Log($"添加按钮盒失败: {ExceptionFormatter.FormatEx(ex)}", "ButtonMission", true);
                }
            }
        }

        /// <summary>
        /// 判断是否需要更新按钮盒
        /// </summary>
        private bool ShouldUpdateButtonBox(BasicButtonBox existingBox, ButtonBoxModel configBox)
        {
            // 检查基本属性是否变更
            if (existingBox.Ip != configBox.Ip 
                || existingBox.Port != configBox.Port 
                || existingBox.GetType().Name != configBox.Type)
            {
                return true;
            }

            // 检查按钮信息是否变更
            return HasButtonConfigsChanged(existingBox, configBox);
        }

        /// <summary>
        /// 检查按钮配置信息是否变更
        /// </summary>
        private bool HasButtonConfigsChanged(BasicButtonBox existingBox, ButtonBoxModel configBox)
        {
            var configButtons = configBox.Buttons ?? new List<ButtonModel>();
            var configDict = configButtons.ToDictionary(b => b.Index);
            var existingDict = existingBox.ButtonConfigs;

            // 检查按钮数量是否变化
            if (existingDict.Count != configDict.Count)
            {
                return true;
            }

            // 检查每个按钮的配置是否变化
            foreach (var configButton in configButtons)
            {
                if (!existingDict.TryGetValue(configButton.Index, out var existingButton))
                {
                    // 新增了按钮
                    return true;
                }

                // 检查按钮配置是否变化
                if (existingButton.TriggerMission != configButton.TriggerMission
                    || existingButton.TriggerMethod != configButton.TriggerMethod
                    || existingButton.TriggerMethodParams != configButton.TriggerMethodParams
                    || existingButton.TriggerState != configButton.TriggerState
                    || existingButton.TriggerDelay != configButton.TriggerDelay)
                {
                    return true;
                }
            }

            // 检查是否有按钮被删除
            foreach (var existingKey in existingDict.Keys)
            {
                if (!configDict.ContainsKey(existingKey))
                {
                    return true;
                }
            }

            return false;
        }

        /// <summary>
        /// 更新按钮盒属性
        /// </summary>
        private void UpdateButtonBox(BasicButtonBox buttonBox, ButtonBoxModel configBox)
        {
            // 如果类型改变，需要重新创建实例
            if (buttonBox.GetType().Name != configBox.Type)
            {
                // 断开旧连接
                buttonBox.Disconnect();
                
                // 从列表中移除
                _buttonBoxes.Remove(buttonBox);
                
                // 创建新实例
                var newBox = CreateButtonBoxInstance(configBox);
                if (newBox != null)
                {
                    _buttonBoxes.Add(newBox);
                }
            }
            else
            {
                // 只更新属性
                bool needReconnect = buttonBox.Ip != configBox.Ip || buttonBox.Port != configBox.Port;
                buttonBox.Ip = configBox.Ip;
                buttonBox.Port = configBox.Port;
                
                // 更新按钮配置信息
                buttonBox.UpdateButtonConfigs(configBox.Buttons);
                
                // 初始化按钮状态（基于配置中的按钮索引）
                var buttonIndices = configBox.Buttons?.Select(b => b.Index).ToList() ?? new List<int>();
                buttonBox.InitializeButtons(buttonIndices);
                
                // 如果IP或端口改变，需要重新连接
                if (needReconnect)
                {
                    buttonBox.Disconnect();
                    buttonBox.Connect();
                }
            }
        }

        /// <summary>
        /// 通过类型字符串创建按钮盒实例
        /// </summary>
        private BasicButtonBox CreateButtonBoxInstance(ButtonBoxModel configBox)
        {
            if (string.IsNullOrWhiteSpace(configBox.Type))
            {
                return null;
            }
            
            try
            {
                // 获取当前命名空间下所有继承自BasicButtonBox的类
                // 跨程序集发现：按钮盒具体类型可能位于卫星插件 dll（StandardScene.Devices.ButtonBox），
                // 用内核同款全域类型发现替代仅扫当前程序集的 GetExecutingAssembly。
                var buttonBoxType = Simple3.Utils.UiTypeDiscovery.AllTypes()
                    .FirstOrDefault(t => t.IsClass 
                        && !t.IsAbstract 
                        && t.Namespace == typeof(BasicButtonBox).Namespace
                        && t.IsSubclassOf(typeof(BasicButtonBox))
                        && t.Name == configBox.Type);
                
                if (buttonBoxType == null)
                {
                    Diagnosis.Log($"未找到按钮盒类型: {configBox.Type}", "ButtonMission", true);
                    return null;
                }
                
                // 使用反射创建实例
                var instance = (BasicButtonBox)Activator.CreateInstance(buttonBoxType);
                
                // 设置属性
                instance.Index = configBox.Index;
                instance.Ip = configBox.Ip;
                instance.Port = configBox.Port;
                
                // 初始化按钮配置信息
                instance.InitializeButtonConfigs(configBox.Buttons);
                
                // 初始化按钮状态（基于配置中的按钮索引）
                var buttonIndices = configBox.Buttons?.Select(b => b.Index).ToList() ?? new List<int>();
                instance.InitializeButtons(buttonIndices);
                
                // 自动连接
                instance.Connect();
                
                return instance;
            }
            catch (Exception ex)
            {
                Diagnosis.Log($"创建按钮盒实例失败: Type={configBox.Type}, Error={ExceptionFormatter.FormatEx(ex)}", "ButtonMission", true);
                return null;
            }
        }

        /// <summary>
        /// 获取当前所有按钮盒实例（只读）
        /// </summary>
        public IReadOnlyList<BasicButtonBox> GetButtonBoxes()
        {
            lock (_syncLock)
            {
                return _buttonBoxes.ToList().AsReadOnly();
            }
        }

        /// <summary>
        /// 执行按钮动作（在独立线程中异步执行，避免阻塞按钮监控循环）
        /// </summary>
        private void ExecuteButtonAction(ButtonModel buttonConfig, BasicButtonBox buttonBox)
        {
           

            Task.Run(() => ExecuteButtonActionInternal(buttonConfig, buttonBox));
        }

        /// <summary>
        /// 实际执行业务方法的内部逻辑，包含成功/失败反馈。
        /// </summary>
        private void ExecuteButtonActionInternal(ButtonModel buttonConfig, BasicButtonBox buttonBox)
        {
            var success = false;
            try
            {
                // 按钮动作执行后清零对应按钮寄存器（具体盒型按需重写，默认空实现）
                buttonBox.ClearButtonRegister(buttonConfig.Index);

                if (string.IsNullOrWhiteSpace(buttonConfig.TriggerMission) ||
                    string.IsNullOrWhiteSpace(buttonConfig.TriggerMethod))
                {
                    // 配置不完整，直接反馈失败
                    Diagnosis.Log("按钮配置缺少 TriggerMission 或 TriggerMethod，无法执行动作", "ButtonMission", true);
                    return;
                }

                var mission = SimpleProject.proj?.Missions?
                    .FirstOrDefault(m => m.GetType().Name == buttonConfig.TriggerMission || m.name == buttonConfig.TriggerMission);

                if (mission == null)
                {
                    Diagnosis.Log($"未找到触发任务: {buttonConfig.TriggerMission}", "ButtonMission", true);
                    return;
                }

                var method = mission.GetType().GetMethod(buttonConfig.TriggerMethod,
                    BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);

                if (method == null)
                {
                    Diagnosis.Log($"任务 {buttonConfig.TriggerMission} 中未找到方法 {buttonConfig.TriggerMethod}", "ButtonMission", true);
                    return;
                }

                var parameters = ParseMethodParameters(buttonConfig.TriggerMethodParams, method);

                if (method.IsStatic)
                {
                    var result = method.Invoke(null, parameters);
                    success = HandleMethodResult(result);
                }
                else
                {
                    var result = method.Invoke(mission, parameters);
                    success = HandleMethodResult(result);
                }
            }
            catch (Exception ex)
            {
                Diagnosis.Log($"执行按钮动作失败: {ExceptionFormatter.FormatEx(ex)}", "ButtonMission", true);
            }
            finally
            {
                // 业务方法执行完成后，回调按钮盒进行反馈（如灯光、蜂鸣等）
                try
                {
                    buttonBox.OnActionExecuted(buttonConfig, success);
                }
                catch (Exception feedbackEx)
                {
                    Diagnosis.Log($"按钮盒执行反馈失败: {ExceptionFormatter.FormatEx(feedbackEx)}", "ButtonMission", true);
                }
            }
        }

        /// <summary>
        /// 处理反射调用结果：支持 Task/Task&lt;bool&gt; 等异步返回类型。
        /// 返回 true 表示执行成功。
        /// </summary>
        private bool HandleMethodResult(object result)
        {
            try
            {
                switch (result)
                {
                    case null:
                        return true;
                    case Task<bool> tb:
                        return tb.GetAwaiter().GetResult();
                    case Task t:
                        t.GetAwaiter().GetResult();
                        return true;
                    case bool b:
                        return b;
                    default:
                        return true;
                }
            }
            catch (Exception ex)
            {
                Diagnosis.Log($"按钮动作方法异步执行失败: {ExceptionFormatter.FormatEx(ex)}", "ButtonMission", true);
                return false;
            }
        }

        /// <summary>
        /// 解析方法参数
        /// </summary>
        private object[] ParseMethodParameters(string paramsStr, MethodInfo methodInfo)
        {
            var paramInfos = methodInfo.GetParameters();

            if (paramInfos.Length == 0)
            {
                return Array.Empty<object>();
            }

            if (string.IsNullOrWhiteSpace(paramsStr))
            {
                return paramInfos.Select(p => p.HasDefaultValue ? p.DefaultValue : GetDefaultValue(p.ParameterType)).ToArray();
            }

            try
            {
                var paramStrings = paramsStr.Split(',');
                var parameters = new List<object>();

                for (int i = 0; i < paramInfos.Length; i++)
                {
                    var paramInfo = paramInfos[i];
                    var paramType = paramInfo.ParameterType;

                    if (i < paramStrings.Length)
                    {
                        var trimmed = paramStrings[i].Trim();
                        parameters.Add(ConvertParameter(trimmed, paramType));
                    }
                    else
                    {
                        parameters.Add(paramInfo.HasDefaultValue ? paramInfo.DefaultValue : GetDefaultValue(paramType));
                    }
                }

                return parameters.ToArray();
            }
            catch (Exception ex)
            {
                Diagnosis.Log($"解析按钮参数失败: {ExceptionFormatter.FormatEx(ex)}", "ButtonMission", true);
                return paramInfos.Select(p => p.HasDefaultValue ? p.DefaultValue : GetDefaultValue(p.ParameterType)).ToArray();
            }
        }

        /// <summary>
        /// 转换参数
        /// </summary>
        private object ConvertParameter(string value, Type targetType)
        {
            if (targetType == typeof(string))
            {
                return value;
            }
            if (targetType == typeof(int) || targetType == typeof(int?))
            {
                return int.TryParse(value, out int result) ? result : (targetType == typeof(int?) ? (int?)null : 0);
            }
            if (targetType == typeof(double) || targetType == typeof(double?))
            {
                return double.TryParse(value, out double result) ? result : (targetType == typeof(double?) ? (double?)null : 0d);
            }
            if (targetType == typeof(float) || targetType == typeof(float?))
            {
                return float.TryParse(value, out float result) ? result : (targetType == typeof(float?) ? (float?)null : 0f);
            }
            if (targetType == typeof(bool) || targetType == typeof(bool?))
            {
                return bool.TryParse(value, out bool result) ? result : (targetType == typeof(bool?) ? (bool?)null : false);
            }
            if (targetType.IsEnum)
            {
                try
                {
                    return Enum.Parse(targetType, value, true);
                }
                catch
                {
                    return Enum.GetValues(targetType).GetValue(0);
                }
            }

            return value;
        }

        /// <summary>
        /// 获取类型默认值
        /// </summary>
        private object GetDefaultValue(Type type)
        {
            if (type.IsValueType)
            {
                return Activator.CreateInstance(type);
            }

            return null;
        }

        /// <summary>
        /// 打开按钮盒管理界面
        /// </summary>
        [MethodMember(Name = "打开管理界面")]
        [I18N.DocumentTranslation(Name = "Open Manager", locale = "en")]
        public static void OpenViewer()
        {
            try { ButtonBoxManager.Open(); }
            catch (Exception ex) { FairyUiHelper.Alert("错误", $"打开按钮盒管理界面失败: {ex.Message}"); }
        }
    }
}
