using Common.Attributes;
using DeviceCommand.Base;
using Prism.Events;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reflection;
using System.Windows.Input;
using UIShare.GlobalVariable;
using UIShare.PubEvent;
using UIShare.UIViewModel;
using UIShare.ViewModelBase;
using ZLGUSBCANFD;

namespace MonitorModule.ViewModels.Dialogs
{
    public class ValueLimitViewModel : DialogViewModelBase
    {
        #region 属性
        private string _Title = "报警设置";

        public string Title
        {
            get { return _Title; }
            set { SetProperty(ref _Title, value); }
        }

        private ValueLimitVM _SelectValueLimitVM;

        public ValueLimitVM SelectValueLimitVM
        {
            get => _SelectValueLimitVM;
            set => SetProperty(ref _SelectValueLimitVM, value);
        }
        private ObservableCollection<ValueLimitVM> _ValueLimitList;
        public ObservableCollection<ValueLimitVM> ValueLimitList
        {
            get => _ValueLimitList;
            set => SetProperty(ref _ValueLimitList, value);
        }
        //private ObservableCollection<string> _DeviceSingleList = new();

        //public ObservableCollection<string> DeviceSingleList
        //{
        //    get => _DeviceSingleList;
        //    set => SetProperty(ref _DeviceSingleList, value);
        //}
        //private string _SelectCurve;

        //public string SelectCurve
        //{
        //    get => _SelectCurve;
        //    set => SetProperty(ref _SelectCurve, value);
        //}

        #endregion
        #region 命令
        public ICommand SaveCommand { get; set; }
        public ICommand CloseCommand { get; set; }
        //public ICommand SelectSignalCommand { get; set; }
        public ICommand DeleteCommand { get; set; }

        #endregion
        private GlobalInfo _globalInfo { get; set; }
        private SystemConfig _systemConfig { get; set; }
        private IScopedProvider _scope { get; set; }
        private DeviceManager? _deviceManager;

        /// <summary>SignalName → CAN信号标识，用于DBC加载/卸载时清理</summary>
        private readonly Dictionary<string, (string Fingerprint, string MethodName)> _canSignalMap = new();

        private SubscriptionToken? _dbcLoadedToken;
        private SubscriptionToken? _dbcUnloadedToken;

        public ValueLimitViewModel(IContainerProvider containerProvider) : base(containerProvider)
        {
            _globalInfo = containerProvider.Resolve<GlobalInfo>();
            _eventAggregator = containerProvider.Resolve<IEventAggregator>();
            SaveCommand = new DelegateCommand(OnSave);
            CloseCommand = new DelegateCommand(OnClose);
            //SelectSignalCommand = new DelegateCommand(SelectSignal);
            DeleteCommand = new DelegateCommand(Deletel);
        }
        #region 命令处理
        private void Deletel()
        {
            if (SelectValueLimitVM == null)
            {
                return;
            }
            else
            {
                ValueLimitList.Remove(SelectValueLimitVM);
                SelectValueLimitVM = null;
            }
        }


        private void InitData()
        {
            ValueLimitList = new ObservableCollection<ValueLimitVM>();
            //DeviceSingleList = new ObservableCollection<string>();
            _canSignalMap.Clear();

            // 1. 加载已保存的 ValueLimitList（保留用户设置）
            if (_systemConfig?.ValueLimitList != null)
            {
                foreach (var item in _systemConfig.ValueLimitList)
                    ValueLimitList.Add(item);
            }

            // 2. 发现设备方法信号并加入 ValueLimitList / DeviceSingleList
            foreach (var (displayName, fingerprint, methodName) in DiscoverDeviceSignals())
            {
                //DeviceSingleList.Add(displayName);
                EnsureValueLimit(fingerprint, displayName, displayName, methodName);
            }

            // 3. 发现 CAN 信号并加入 ValueLimitList，同时收集有效信号名
            var validCanSignalNames = new HashSet<string>();
            foreach (var (displayName, fingerprint, methodName) in DiscoverCanSignals())
            {
                _canSignalMap[displayName] = (fingerprint, methodName);
                EnsureValueLimit(fingerprint, displayName, displayName, methodName);
                validCanSignalNames.Add(displayName);
            }

            // 4. 清理已不存在于 DBC 中的 CAN 信号（Fingerprint 以 "CAN" 开头且不在有效集合中）
            var staleCanSignals = ValueLimitList
                .Where(x => !string.IsNullOrEmpty(x.Fingerprint) &&
                            x.Fingerprint.StartsWith("CAN") &&
                            !validCanSignalNames.Contains(x.SignalName))
                .ToList();
            foreach (var item in staleCanSignals)
                ValueLimitList.Remove(item);
        }

        /// <summary>
        /// 发现当前作用域所有可监测的设备方法信号（与 MonitorViewModel 逻辑一致）。
        /// 返回 (DisplayName, Fingerprint, MethodName) 列表。
        /// </summary>
        private IEnumerable<(string DisplayName, string Fingerprint, string MethodName)> DiscoverDeviceSignals()
        {
            if (_deviceManager?.DeviceMap == null) yield break;

            var instanceToFp = BuildInstanceToFingerprint();
            foreach (var kvp in _deviceManager.DeviceMap)
            {
                string deviceName = kvp.Key;
                var device = kvp.Value;

                if (!instanceToFp.TryGetValue(device, out string? fingerprint))
                    continue;

                var methods = device.GetType().GetMethods(BindingFlags.Public | BindingFlags.Instance)
                    .Where(m =>
                    {
                        if (m.GetCustomAttribute<MonitorableAttribute>() == null) return false;
                        if (m.ReturnType != typeof(Task<string>)) return false;
                        var parms = m.GetParameters();
                        return parms.Length == 0 ||
                               (parms.Length == 1 && parms[0].ParameterType == typeof(CancellationToken));
                    });

                foreach (var method in methods)
                {
                    var attr = method.GetCustomAttribute<MonitorableAttribute>();
                    string displayName = !string.IsNullOrEmpty(attr?.Description)
                        ? $"{deviceName}.{attr.Description}"
                        : $"{deviceName}.{method.Name}";
                    yield return (displayName, fingerprint, method.Name);
                }
            }
        }

        /// <summary>
        /// 构建设备实例 → 硬件指纹的反向查找表。
        /// </summary>
        private Dictionary<object, string> BuildInstanceToFingerprint()
        {
            var map = new Dictionary<object, string>(ReferenceEqualityComparer.Instance);
            if (_globalInfo?.HardwarePool == null) return map;

            foreach (var poolEntry in _globalInfo.HardwarePool)
            {
                var lazy = poolEntry.Value;
                if (lazy.IsValueCreated && lazy.Value != null)
                    map[lazy.Value] = poolEntry.Key;
            }
            return map;
        }

        /// <summary>
        /// 发现当前已加载 DBC 中的 CAN 信号（以 ConfigurationList 为白名单）。
        /// 返回 (DisplayName, Fingerprint, MethodName) 列表。
        /// </summary>
        private IEnumerable<(string DisplayName, string Fingerprint, string MethodName)> DiscoverCanSignals()
        {
            if (_deviceManager?.CANFD?.DBCParser?.MsgDatabase == null) yield break;
            if (_systemConfig?.ConfigurationList == null) yield break;

            var msgDb = _deviceManager.CANFD.DBCParser.MsgDatabase;
            string canDeviceFingerprint = _deviceManager.GetCanDeviceFingerprint();
            foreach (var cfg in _systemConfig.ConfigurationList)
            {
                if (string.IsNullOrEmpty(cfg.SignalName)) continue;
                if (cfg.Channel < 0 || cfg.Channel >= msgDb.Count) continue;

                string fingerprint = CANSignalBroadcaster.BuildFingerprint(canDeviceFingerprint, (uint)cfg.Channel);
                string methodName = CANSignalBroadcaster.BuildMethodName((uint)cfg.MessageID, cfg.SignalName);
                string displayName = CANSignalBroadcaster.BuildDisplayName(cfg.MessageName, cfg.SignalName);

                if (ExistsInDbc(methodName, msgDb[cfg.Channel]))
                    yield return (displayName, fingerprint, methodName);
            }
        }

        /// <summary>
        /// 判断指定的 MethodName 是否存在于该通道的 DBC 消息数据库中。
        /// </summary>
        private static bool ExistsInDbc(string methodName, List<_Msg_> messages)
        {
            if (string.IsNullOrEmpty(methodName)) return false;
            int dotIndex = methodName.IndexOf('.');
            if (dotIndex <= 0 || dotIndex >= methodName.Length - 1) return false;

            if (!uint.TryParse(methodName.Substring(0, dotIndex), System.Globalization.NumberStyles.HexNumber, null, out uint msgId))
                return false;
            string signalName = methodName.Substring(dotIndex + 1);

            return messages.Any(m => m.msg_id == msgId && m.signal_Name != null && m.signal_Name.Contains(signalName));
        }

        /// <summary>
        /// 确保 ValueLimitList 中存在指定信号；不存在则添加默认值。
        /// </summary>
        private void EnsureValueLimit(string fingerprint, string displayName, string signalName, string methodName = "")
        {
            if (ValueLimitList.Any(x => x.SignalName == signalName)) return;

            ValueLimitList.Add(new ValueLimitVM
            {
                DisplayName = displayName,
                Fingerprint = fingerprint,
                SignalName = signalName,
                MethodName = methodName,
                Upper = 9999,
                Lower = -9999,
                UpperExtreme = 9999,
                LowerExtreme = -9999,
            });
        }

        /// <summary>
        /// 从 ValueLimitList 和 DeviceSingleList 中移除指定信号。
        /// </summary>
        private void RemoveValueLimit(string signalName)
        {
            var item = ValueLimitList.FirstOrDefault(x => x.SignalName == signalName);
            if (item != null) ValueLimitList.Remove(item);

            //if (DeviceSingleList.Contains(signalName))
            //    DeviceSingleList.Remove(signalName);
        }

        //private void SelectSignal()
        //{
        //    if (ValueLimitList.Where(x => x.SignalName == SelectCurve).Count() > 0)
        //    {
        //        return;
        //    }
        //    ValueLimitList.Add(new ValueLimitVM
        //    {
        //        SignalName = SelectCurve,
        //        Upper = 9999,
        //        Lower = -9999,
        //        UpperExtreme = 9999,
        //        LowerExtreme = -9999,
        //    });
        //}

        private void OnClose()
        {
            RequestClose.Invoke();
        }

        private void OnSave()
        {
            _systemConfig.ValueLimitList = ValueLimitList;
            ConfigService.Save(_systemConfig);
        }
        #endregion
        public override void OnDialogOpened(IDialogParameters parameters)
        {
            // 1. 优先执行基类的打开逻辑（如果基类有需要初始化的通用事务）
            base.OnDialogOpened(parameters);

            // 2. 解析参数
            if (parameters != null && parameters.ContainsKey("Scope")) // 修复：Prism 中应使用 ContainsKey
            {
                _scope = parameters.GetValue<IScopedProvider>("Scope");
                _systemConfig = _scope.Resolve<SystemConfig>();
                _deviceManager = _scope.Resolve<DeviceManager>();

                // 3. 订阅 DBC 加载/卸载事件
                _dbcLoadedToken = _eventAggregator.GetEvent<DBCLoadedEvent>()
                    .Subscribe(OnDbcLoaded, ThreadOption.UIThread);
                _dbcUnloadedToken = _eventAggregator.GetEvent<DBCUnloadedEvent>()
                    .Subscribe(OnDbcUnloaded, ThreadOption.UIThread);

                // 4. 初始化数据
                InitData();
            }
        }

        public override void OnDialogClosed()
        {
            base.OnDialogClosed();

            // 取消 DBC 事件订阅，避免内存泄漏
            if (_dbcLoadedToken != null)
                _eventAggregator.GetEvent<DBCLoadedEvent>().Unsubscribe(_dbcLoadedToken);
            if (_dbcUnloadedToken != null)
                _eventAggregator.GetEvent<DBCUnloadedEvent>().Unsubscribe(_dbcUnloadedToken);
        }

        /// <summary>
        /// DBCLoadedEvent 回调：清理该通道中不存在于 DBC 的 CAN 信号限制项。
        /// </summary>
        private void OnDbcLoaded(DBCLoadedArgs args)
        {
            if (args.Scope != _systemConfig?.Title) return;
            if (_deviceManager?.CANFD?.DBCParser?.MsgDatabase == null) return;

            int channel = (int)args.Channel;
            var msgDb = _deviceManager.CANFD.DBCParser.MsgDatabase;
            if (channel < 0 || channel >= msgDb.Count) return;

            string canDeviceFingerprint = _deviceManager.GetCanDeviceFingerprint();
            string fingerprint = CANSignalBroadcaster.BuildFingerprint(canDeviceFingerprint, args.Channel);

            // 1. 移除该通道中已失效的 CAN 信号限制项
            var staleSignals = _canSignalMap
                .Where(kvp => kvp.Value.Fingerprint == fingerprint &&
                              !ExistsInDbc(kvp.Value.MethodName, msgDb[channel]))
                .Select(kvp => kvp.Key)
                .ToList();

            foreach (var signalName in staleSignals)
            {
                RemoveValueLimit(signalName);
                _canSignalMap.Remove(signalName);
            }

            // 2. 根据 ConfigurationList 补充新加载的有效信号
            if (_systemConfig?.ConfigurationList != null)
            {
                foreach (var cfg in _systemConfig.ConfigurationList.Where(c => c.Channel == channel))
                {
                    if (string.IsNullOrEmpty(cfg.SignalName)) continue;

                    string methodName = CANSignalBroadcaster.BuildMethodName((uint)cfg.MessageID, cfg.SignalName);
                    string displayName = CANSignalBroadcaster.BuildDisplayName(cfg.MessageName, cfg.SignalName);

                    if (ExistsInDbc(methodName, msgDb[channel]))
                    {
                        _canSignalMap[displayName] = (fingerprint, methodName);
                        //if (!DeviceSingleList.Contains(displayName))
                        //    DeviceSingleList.Add(displayName);
                        EnsureValueLimit(fingerprint, displayName, displayName, methodName);
                    }
                }
            }
        }

        /// <summary>
        /// DBCUnloadedEvent 回调：删除该通道所有 CAN 信号的限制项。
        /// </summary>
        private void OnDbcUnloaded(DBCUnloadedArgs args)
        {
            if (args.Scope != _systemConfig?.Title) return;

            string canDeviceFingerprint = _deviceManager.GetCanDeviceFingerprint();
            string fingerprint = CANSignalBroadcaster.BuildFingerprint(canDeviceFingerprint, args.Channel);
            var toRemove = _canSignalMap
                .Where(kvp => kvp.Value.Fingerprint == fingerprint)
                .Select(kvp => kvp.Key)
                .ToList();

            foreach (var signalName in toRemove)
            {
                RemoveValueLimit(signalName);
                _canSignalMap.Remove(signalName);
            }
        }
    }
}
