using Microsoft.Win32;
using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using UIShare.GlobalVariable;
using UIShare.UIViewModel;
using UIShare.ViewModelBase;
using ZLGUSBCANFD;

namespace CANModule.ViewModels
{
    public class ZLGCANFDViewModel : NavigateViewModelBase
    {
        #region 字段
        private ZLGCANFD? _canfd;
        private SystemConfig? _systemConfig;
        private CancellationTokenSource? _refreshCts;
        private readonly DeviceManager _deviceManager;
        #endregion

        #region 属性
        private string _Title = "周立功CAN";
        public string Title
        {
            get => _Title;
            set => SetProperty(ref _Title, value);
        }

        private ObservableCollection<CanMessageShowVM> _CanMessageList = new();
        public ObservableCollection<CanMessageShowVM> CanMessageList
        {
            get => _CanMessageList;
            set => SetProperty(ref _CanMessageList, value);
        }

        private int _DBCChannel = 0;
        public int DBCChannel
        {
            get => _DBCChannel;
            set => SetProperty(ref _DBCChannel, value);
        }

        private bool _IsDirectlySend = false;
        public bool IsDirectlySend
        {
            get => _IsDirectlySend;
            set => SetProperty(ref _IsDirectlySend, value);
        }

        private ObservableCollection<string> _Message;
        public ObservableCollection<string> Message
        {
            get => _Message;
            set => SetProperty(ref _Message, value);
        }

        private ObservableCollection<string> _Signal;
        public ObservableCollection<string> Signal
        {
            get => _Signal;
            set => SetProperty(ref _Signal, value);
        }

        private byte _channel;
        private string _selectedMessage;
        public string SelectedMessage
        {
            get => _selectedMessage;
            set
            {
                if (_selectedMessage != value)
                {
                    if (!string.IsNullOrEmpty(value) && _canfd != null)
                    {
                        var db = _canfd.DBCParser.MsgDatabase;
                        if (_channel >= 0 && _channel < db.Count)
                        {
                            var targetMsg = db[(int)_channel]
                                .FirstOrDefault(x => $"[0x{x.msg_id:X}]{x.msg_name}" == value);

                            if (targetMsg != null && targetMsg.signal_Name != null)
                            {
                                Signal = new ObservableCollection<string>(targetMsg.signal_Name);
                            }
                            else
                            {
                                Signal = new ObservableCollection<string>();
                            }
                        }
                    }
                    else
                    {
                        Signal = new ObservableCollection<string>();
                    }
                    _selectedMessage = value;
                    RaisePropertyChanged();
                }
            }
        }

        private string _selectedSignal;
        public string SelectedSignal
        {
            get => _selectedSignal;
            set => SetProperty(ref _selectedSignal, value);
        }

        private string _signalValue;
        public string SignalValue
        {
            get => _signalValue;
            set => SetProperty(ref _signalValue, value);
        }

        private string _cycleSendInterval;
        public string CycleSendInterval
        {
            get => _cycleSendInterval;
            set => SetProperty(ref _cycleSendInterval, value);
        }

        private int _messageSendChannel = 0;
        public int MessageSendChannel
        {
            get => _messageSendChannel;
            set => SetProperty(ref _messageSendChannel, value);
        }

        public string BLFPath
        {
            get => _systemConfig?.DefaultBLFFilePath ?? "";
            set
            {
                if (_systemConfig != null && _systemConfig.DefaultBLFFilePath != value)
                {
                    _systemConfig.DefaultBLFFilePath = value;
                    RaisePropertyChanged();
                }
            }
        }

        public string DBCPath
        {
            get => _systemConfig?.DefaultDBCFilePath ?? "";
            set
            {
                if (_systemConfig != null && _systemConfig.DefaultDBCFilePath != value)
                {
                    _systemConfig.DefaultDBCFilePath = value;
                    RaisePropertyChanged();
                }
            }
        }

        private bool _IsSaved;
        public bool IsSaved
        {
            get => _IsSaved;
            set => SetProperty(ref _IsSaved, value);
        }

        public ObservableCollection<AutoDBCLoadItem> DBCAutoLoadList
        {
            get => _systemConfig?.DBCAutoLoadList ?? new ObservableCollection<AutoDBCLoadItem>();
        }

        private AutoDBCLoadItem _SelectedDcAutoLoad;
        public AutoDBCLoadItem SelectedDcAutoLoad
        {
            get => _SelectedDcAutoLoad;
            set => SetProperty(ref _SelectedDcAutoLoad, value);
        }

        // ===== 自定义报文发送属性 =====
        private APP_CHANNEL[] _appChannelNames = Enum.GetValues<APP_CHANNEL>();
        public APP_CHANNEL[] APP_CHANNEL
        {
            get => _appChannelNames;
            set => SetProperty(ref _appChannelNames, value);
        }

        private APP_CHANNEL _aIdxChn;
        public APP_CHANNEL AIdxChn
        {
            get => _aIdxChn;
            set => SetProperty(ref _aIdxChn, value);
        }

        private int _aID;
        public int AID
        {
            get => _aID;
            set => SetProperty(ref _aID, value);
        }

        private bool _aIsTx;
        public bool AIsTx
        {
            get => _aIsTx;
            set => SetProperty(ref _aIsTx, value);
        }

        private bool _aIsExt;
        public bool AIsExt
        {
            get => _aIsExt;
            set => SetProperty(ref _aIsExt, value);
        }

        private bool _aIsRemote;
        public bool AIsRemote
        {
            get => _aIsRemote;
            set => SetProperty(ref _aIsRemote, value);
        }

        private byte _aDlc;
        public byte ADLC
        {
            get => _aDlc;
            set => SetProperty(ref _aDlc, value);
        }

        private byte[] _aDataArray;
        public byte[] ADataArray
        {
            get => _aDataArray;
            set => SetProperty(ref _aDataArray, value);
        }

        private bool _aIsFD = true;
        public bool AIsFD
        {
            get => _aIsFD;
            set => SetProperty(ref _aIsFD, value);
        }

        private bool _aIsBRS = false;
        public bool AIsBRS
        {
            get => _aIsBRS;
            set => SetProperty(ref _aIsBRS, value);
        }

        private bool _AutoSetting = true;
        public bool AutoSetting
        {
            get => _AutoSetting;
            set => SetProperty(ref _AutoSetting, value);
        }

        private string _CustomMessage = "[00,11,22,33,AA,BB,CC,DD]";
        public string CustomMessage
        {
            get => _CustomMessage;
            set => SetProperty(ref _CustomMessage, value);
        }

        private float _CustomSendCycleInterval = 0.0f;
        public float CustomSendCycleInterval
        {
            get => _CustomSendCycleInterval;
            set => SetProperty(ref _CustomSendCycleInterval, value);
        }

        //private bool _UpdateToDB;
        //public bool UpdateToDB
        //{
        //    get => _UpdateToDB;
        //    set => SetProperty(ref _UpdateToDB, value);
        //}

        // ===== 连接状态 =====
        private bool _IsDeviceOpened;
        public bool IsDeviceOpened
        {
            get => _IsDeviceOpened;
            set => SetProperty(ref _IsDeviceOpened, value);
        }

        private ObservableCollection<int> _ChannelList;
        public ObservableCollection<int> ChannelList
        {
            get => _ChannelList;
            set => SetProperty(ref _ChannelList, value);
        }

        private int _SelectedChannel = -1;
        public int SelectedChannel
        {
            get => _SelectedChannel;
            set
            {
                if (_SelectedChannel != value)
                {
                    _SelectedChannel = value;
                    if (value >= 0 && _canfd != null)
                    {
                        _canfd.初始化并启动通道((uint)value);
                    }
                    RaisePropertyChanged();
                }
            }
        }
        #endregion

        #region 命令
        public ICommand SelectBLFPathCommand { get; set; }
        public ICommand SaveBLFPathCommand { get; set; }
        public ICommand StartTranscribeCommand { get; set; }
        public ICommand EndTranscribeCommand { get; set; }
        public ICommand ConnectCanCommand { get; set; }
        public ICommand CloseCanCommand { get; set; }
        public ICommand ClearCycleCommand { get; set; }
        public ICommand UpLoadDBCCommand { get; set; }
        public ICommand ChangeDBCCommand { get; set; }
        public ICommand LoadDBCCommand { get; set; }
        public ICommand LoadMessageCommand { get; set; }
        public ICommand SetAndSendMessageCommand { get; set; }
        public ICommand DeleteDcAutoLoadCommand { get; set; }
        public ICommand SendCustomMessageCommand { get; set; }
        public ICommand LoadCommand { get; set; }
        #endregion

        public ZLGCANFDViewModel(IContainerProvider containerProvider) : base(containerProvider)
        {
            _systemConfig = containerProvider.Resolve<SystemConfig>();
            _deviceManager = containerProvider.Resolve<DeviceManager>();
            _canfd = _deviceManager.CANFD;
            SelectBLFPathCommand = new DelegateCommand(SelectBLFPath);
            SaveBLFPathCommand = new DelegateCommand(SaveBLFPath);
            StartTranscribeCommand = new DelegateCommand(StartTranscribe);
            EndTranscribeCommand = new DelegateCommand(EndTranscribe);
            ConnectCanCommand = new DelegateCommand(ConnectCan);
            CloseCanCommand = new DelegateCommand(CloseCan);
            ClearCycleCommand = new DelegateCommand(ClearCycle);
            UpLoadDBCCommand = new DelegateCommand(UpLoadDBC);
            ChangeDBCCommand = new DelegateCommand(ChangeDBC);
            LoadDBCCommand = new DelegateCommand(LoadDBC);
            SetAndSendMessageCommand = new DelegateCommand(SetAndSendMessage);
            LoadMessageCommand = new DelegateCommand(LoadMessage);
            DeleteDcAutoLoadCommand = new DelegateCommand(DeleteDcAutoLoad);
            SendCustomMessageCommand = new DelegateCommand(SendCustomMessage);
            _canfd.OnDbcMessageDecoded += OnDbcMessageDecoded;
            LoadCommand = new DelegateCommand(Load);
        }

         #region Dialog 生命周期
        public override void OnNavigatedTo(NavigationContext navigationContext)
        {
            if (_canfd != null)
            {
               
            }

            RaisePropertyChanged(nameof(BLFPath));
            RaisePropertyChanged(nameof(DBCPath));
            RaisePropertyChanged(nameof(DBCAutoLoadList));
        }

        public override void OnNavigatedFrom(NavigationContext navigationContext)
        {
            if (_canfd != null)
            {
                _canfd.OnDbcMessageDecoded -= OnDbcMessageDecoded;
            }
            _refreshCts?.Cancel();
        }
        #endregion

        #region 命令处理
        private void Load()
        {
            int maxCh = _canfd?.DBCParser.MaxChannels ?? 4;
            ChannelList = new ObservableCollection<int>(Enumerable.Range(0, maxCh));
        }

        private void SendCustomMessage()
        {
            if (_canfd == null) return;

            try
            {
                ADataArray = 报文转换(CustomMessage);
                if (ADataArray.Length > byte.MaxValue) throw new Exception("报文数量超过上限!");
                if (AutoSetting)
                {
                    ADLC = (byte)ADataArray.Length;
                }
            }
            catch (Exception ex)
            {
                ShowErrorMessageBox($"报文转换失败：{ex.Message}", () => { });
                return;
            }

            _canfd.发送自定义报文(
                (uint)AIdxChn,
                AID.ToString(),
                ADataArray,
                ADLC,
                AIsExt,
                AIsFD,
                AIsBRS);
        }

        private void DeleteDcAutoLoad()
        {
            if (SelectedDcAutoLoad != null)
            {
                DBCAutoLoadList.Remove(SelectedDcAutoLoad);
            }
        }

        private void LoadMessage()
        {
            if (_canfd == null) return;

            if (MessageSendChannel >= 0)
            {
                var db = _canfd.DBCParser.MsgDatabase;
                if (MessageSendChannel < db.Count)
                {
                    Message = new ObservableCollection<string>(
                        db[MessageSendChannel].Select(s => $"[0x{s.msg_id:X}]{s.msg_name}"));
                }
            }
        }

        private void SetAndSendMessage()
        {
            if (_canfd == null) return;

            if (int.TryParse(CycleSendInterval, out int sendPeriod) &&
                double.TryParse(SignalValue, out double SValue) &&
                MessageSendChannel >= 0)
            {
                _channel = (byte)MessageSendChannel;
                var message = SelectedMessage.Split(']')[1];

                // 通过 DBC 查找帧 ID
                var db = _canfd.DBCParser.MsgDatabase;
                if (MessageSendChannel < db.Count)
                {
                    var targetMsg = db[MessageSendChannel]
                        .FirstOrDefault(x => $"[0x{x.msg_id:X}]{x.msg_name}" == SelectedMessage);

                    if (targetMsg != null)
                    {
                        _canfd.设置报文((uint)MessageSendChannel, targetMsg.msg_id.ToString(), SelectedSignal, SValue, sendPeriod, IsDirectlySend);
                    }
                }
            }
        }

        private void UpLoadDBC()
        {
            if (_canfd == null) return;

            // 释放当前通道的 DBC
            if (DBCChannel >= 0)
            {
                _canfd.释放通道DBC((uint)DBCChannel);
            }
        }

        private void ChangeDBC()
        {
            var dialog = new OpenFileDialog
            {
                Title = "更换DBC文件",
                Filter = "DBC 文件 (*.dbc)|*.dbc|所有文件 (*.*)|*.*",
                DefaultExt = ".dbc",
            };
            if (dialog.ShowDialog() == true)
            {
                DBCPath = System.IO.Path.GetFullPath(dialog.FileName);
            }
        }

        private void LoadDBC()
        {
            if (_canfd == null || DBCChannel < 0) return;

            bool re = _canfd.加载通道DBC文件((uint)DBCChannel, DBCPath);

            if (re && IsSaved)
            {
                var item = DBCAutoLoadList.FirstOrDefault(s => s.DBCChannel == DBCChannel);
                if (item == null)
                {
                    DBCAutoLoadList.Add(new AutoDBCLoadItem
                    {
                        DBCFilePath = DBCPath,
                        DBCChannel = DBCChannel
                    });
                }
                else
                {
                    DBCAutoLoadList.Remove(item);
                    DBCAutoLoadList.Add(new AutoDBCLoadItem
                    {
                        DBCFilePath = DBCPath,
                        DBCChannel = DBCChannel
                    });
                }
                ConfigService.Save(_systemConfig);
            }
        }
        private void ClearCycle()
        {
            _canfd?.停止所有循环发送();
        }

        private void CloseCan()
        {
            if (_canfd == null) return;

            _canfd.关闭CAN卡设备();
            IsDeviceOpened = false;
            _refreshCts?.Cancel();
        }

        private void ConnectCan()
        {
            if (_canfd == null) return;

            bool re = _canfd.打开设备();
            IsDeviceOpened = re;

            if (re)
            {
                // 启动实时报文刷新
                _refreshCts?.Cancel();
                _refreshCts = new CancellationTokenSource();
                _ = Refresh(_refreshCts.Token);
            }
        }

        private void EndTranscribe()
        {
            // TODO: BLF 录制功能在 ZLGCANFD 中未实现，暂不支持
            ShowInfoMessageBox("BLF 录制功能尚未在此硬件驱动中实现。", () => { });
        }

        private void StartTranscribe()
        {
            // TODO: BLF 录制功能在 ZLGCANFD 中未实现，暂不支持
            ShowInfoMessageBox("BLF 录制功能尚未在此硬件驱动中实现。", () => { });
        }

        private void SaveBLFPath()
        {
            // 路径已直接绑定到 SystemConfig，无需额外操作
        }

        private void SelectBLFPath()
        {
            var dialog = new SaveFileDialog
            {
                Title = "保存 CAN报文回放 BLF 文件",
                Filter = "BLF 文件 (*.blf)|*.blf|所有文件 (*.*)|*.*",
                DefaultExt = ".blf",
                FileName = "log.blf",
                OverwritePrompt = true
            };
            if (dialog.ShowDialog() == true)
            {
                BLFPath = System.IO.Path.GetFullPath(dialog.FileName);
            }
        }

        #endregion

        #region 辅助方法
        public byte[] 报文转换(string s)
        {
            s = s.Replace("[", string.Empty).Replace("]", string.Empty);
            var strs = s.Split(',', StringSplitOptions.RemoveEmptyEntries);
            byte[] bytes = new byte[strs.Length];
            for (int i = 0; i < strs.Length; i++)
            {
                bytes[i] = Convert.ToByte(strs[i], 16);
            }
            return bytes;
        }

        private async Task Refresh(CancellationToken ct = default)
        {
            while (!ct.IsCancellationRequested)
            {
                // 通过 OnDbcMessageDecoded 事件已实时更新 CanMessageList
                // 此处仅做周期性 UI 刷新触发
                await Task.Delay(50, ct);
            }
        }

        private void OnDbcMessageDecoded(uint channel, ZDBC.DBCMessage msg)
        {
            // DBC 解码后的报文回调
            Application.Current.Dispatcher.BeginInvoke(() =>
            {
                var msgName = System.Text.Encoding.Default.GetString(msg.strName).TrimEnd('\0');
                var find = CanMessageList.FirstOrDefault(s => s.报文ID == (int)msg.nID&& s.通道==channel);
                if (find != null)
                {
                    find.通道 = (byte)channel;
                    find.报文ID = (int)msg.nID;
                    find.时间戳 = (ulong)DateTimeOffset.Now.ToUnixTimeMilliseconds(); ;
                    find.长度 = (byte)msg.nSize;
                }
                else
                {
                    CanMessageList.Add(new CanMessageShowVM
                    {
                        通道 = (byte)channel,
                        报文ID = (int)msg.nID,
                        时间戳 = (ulong)DateTimeOffset.Now.ToUnixTimeMilliseconds(),
                        长度 = (byte)msg.nSize
                    });
                }
            });
        }

        private string 十六进制字符串转换(System.Span<byte> s)
        {
            if (s == null || s.Length == 0)
                return "[]";

            var sb = new StringBuilder();
            sb.Append('[');
            for (int i = 0; i < s.Length; i++)
            {
                sb.Append("0x");
                sb.Append(s[i].ToString("X2"));
                if (i < s.Length - 1)
                    sb.Append(", ");
            }
            sb.Append(']');
            return sb.ToString();
        }
        #endregion
    }
}
