using DeviceCommand.Devices;
using Prism.Commands;
using Prism.Ioc;
using System;
using System.Threading;
using System.Windows.Input;
using UIShare.GlobalVariable;
using UIShare.ViewModelBase;

namespace DeviceEditModule.ViewModels
{
    /// <summary>
    /// N36200 宽范围可编程直流电源控制面板 ViewModel。
    /// <para>
    /// 注册为 Navigation View，可通过 EventAggregator 添加为 DialogMangerView 中的 Tab：
    /// <code>
    /// var view = container.Resolve&lt;N36200View&gt;();
    /// (view.DataContext as N36200ViewModel)?.Initialize("N36200");
    /// _eventAggregator.GetEvent&lt;AddDialogTabEvent&gt;().Publish(
    ///     new DialogTabInfo { Title = "N36200", Content = view });
    /// </code>
    /// </para>
    /// </summary>
    public class N36200ViewModel : NavigateViewModelBase, IDisposable
    {
        #region 私有字段

        private readonly DeviceManager _deviceManager;
        private N36200? _device;
        private CancellationTokenSource? _cts;

        #endregion

        #region 设备信息属性

        private string _deviceName = "N36200";
        public string DeviceName
        {
            get => _deviceName;
            set => SetProperty(ref _deviceName, value);
        }

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

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

        #endregion

        #region 输入参数属性

        private double _voltage = 12.0;
        /// <summary>待设置的输出电压值（V）。</summary>
        public double Voltage
        {
            get => _voltage;
            set => SetProperty(ref _voltage, value);
        }

        private double _currentLimit = 5.0;
        /// <summary>待设置的限流值（A）。</summary>
        public double CurrentLimit
        {
            get => _currentLimit;
            set => SetProperty(ref _currentLimit, value);
        }

        private string _selectedMode = "NORMal";
        /// <summary>待设置的运行模式：NORMal / CHARge / SEQuence / CPOWer / CARWave / APG。</summary>
        public string SelectedMode
        {
            get => _selectedMode;
            set => SetProperty(ref _selectedMode, value);
        }

        private double _ovpValue = 15.0;
        /// <summary>过压保护值（V）。</summary>
        public double OvpValue
        {
            get => _ovpValue;
            set => SetProperty(ref _ovpValue, value);
        }

        private double _ocpValue = 6.0;
        /// <summary>过流保护值（A）。</summary>
        public double OcpValue
        {
            get => _ocpValue;
            set => SetProperty(ref _ocpValue, value);
        }

        private double _uvpValue = 0.0;
        /// <summary>欠压保护值（V）。</summary>
        public double UvpValue
        {
            get => _uvpValue;
            set => SetProperty(ref _uvpValue, value);
        }

        private double _oppValue = 100.0;
        /// <summary>过功率保护值（W）。</summary>
        public double OppValue
        {
            get => _oppValue;
            set => SetProperty(ref _oppValue, value);
        }

        #endregion

        #region 测量结果属性

        private string _measuredVoltage = "—";
        public string MeasuredVoltage
        {
            get => _measuredVoltage;
            set => SetProperty(ref _measuredVoltage, value);
        }

        private string _measuredCurrent = "—";
        public string MeasuredCurrent
        {
            get => _measuredCurrent;
            set => SetProperty(ref _measuredCurrent, value);
        }

        private string _measuredPower = "—";
        public string MeasuredPower
        {
            get => _measuredPower;
            set => SetProperty(ref _measuredPower, value);
        }

        private string _deviceStatus = "—";
        /// <summary>设备状态字（OUTPut:STATe? 查询结果）。</summary>
        public string DeviceStatus
        {
            get => _deviceStatus;
            set => SetProperty(ref _deviceStatus, value);
        }

        private string _responseLog = string.Empty;
        /// <summary>命令响应日志（最新消息在顶部）。</summary>
        public string ResponseLog
        {
            get => _responseLog;
            set => SetProperty(ref _responseLog, value);
        }

        #endregion

        #region 命令

        public ICommand QueryIdentityCommand    { get; }
        public ICommand ResetDeviceCommand      { get; }
        public ICommand OutputOnCommand         { get; }
        public ICommand OutputOffCommand        { get; }
        public ICommand SetVoltageCommand       { get; }
        public ICommand SetCurrentCommand       { get; }
        public ICommand SetModeCommand          { get; }
        public ICommand QueryAllMeasureCommand  { get; }
        public ICommand QueryStatusCommand      { get; }
        public ICommand SetOvpCommand           { get; }
        public ICommand SetOcpCommand           { get; }
        public ICommand SetUvpCommand           { get; }
        public ICommand SetOppCommand           { get; }
        public ICommand ClearAlarmCommand       { get; }

        #endregion

        public N36200ViewModel(IContainerProvider containerProvider) : base(containerProvider)
        {
            _deviceManager = containerProvider.Resolve<DeviceManager>();

            QueryIdentityCommand   = new DelegateCommand(async () => await Exec(async () => AppendLog("IDN: " + await _device!.查询设备标识(Ct()))));
            ResetDeviceCommand     = new DelegateCommand(async () => await Exec(async () => { await _device!.重置设备(Ct()); AppendLog("设备已重置（耗时约10s）"); }));
            OutputOnCommand        = new DelegateCommand(async () => await Exec(async () => { await _device!.设置DC输出(true, Ct()); AppendLog("输出已开启"); }));
            OutputOffCommand       = new DelegateCommand(async () => await Exec(async () => { await _device!.设置DC输出(false, Ct()); AppendLog("输出已关闭"); }));
            SetVoltageCommand      = new DelegateCommand(async () => await Exec(async () => { await _device!.设置电压(Voltage, Ct()); AppendLog($"电压已设为 {Voltage} V"); }));
            SetCurrentCommand      = new DelegateCommand(async () => await Exec(async () => { await _device!.设置电流(CurrentLimit, Ct()); AppendLog($"限流已设为 {CurrentLimit} A"); }));
            SetModeCommand         = new DelegateCommand(async () => await Exec(async () => { await _device!.设置运行模式(SelectedMode, Ct()); AppendLog($"模式已设为 {SelectedMode}"); }));
            SetOvpCommand          = new DelegateCommand(async () => await Exec(async () => { await _device!.设置过压保护_OVP(OvpValue, Ct()); AppendLog($"OVP已设为 {OvpValue} V"); }));
            SetOcpCommand          = new DelegateCommand(async () => await Exec(async () => { await _device!.设置过流保护_OCP(OcpValue, Ct()); AppendLog($"OCP已设为 {OcpValue} A"); }));
            SetUvpCommand          = new DelegateCommand(async () => await Exec(async () => { await _device!.设置过欠压保护_UVP(UvpValue, Ct()); AppendLog($"UVP已设为 {UvpValue} V"); }));
            SetOppCommand          = new DelegateCommand(async () => await Exec(async () => { await _device!.设置过功率保护_OPP(OppValue, Ct()); AppendLog($"OPP已设为 {OppValue} W"); }));
            ClearAlarmCommand      = new DelegateCommand(async () => await Exec(async () => { await _device!.清除告警(Ct()); AppendLog("告警已清除"); }));

            QueryStatusCommand     = new DelegateCommand(async () => await Exec(async () =>
            {
                DeviceStatus = await _device!.查询设备状态字(Ct());
                AppendLog($"状态字: {DeviceStatus}");
            }));

            QueryAllMeasureCommand = new DelegateCommand(async () => await Exec(async () =>
            {
                MeasuredVoltage = await _device!.查询实际电压(Ct());
                MeasuredCurrent = await _device!.查询实际电流(Ct());
                MeasuredPower   = await _device!.查询实际功率(Ct());
                AppendLog($"测量 → 电压:{MeasuredVoltage}V 电流:{MeasuredCurrent}A 功率:{MeasuredPower}W");
            }));

            Initialize();
        }

        #region 初始化 / Navigation

        /// <summary>
        /// 从 DeviceManager 中查找 N36200 设备实例。
        /// 优先按 <paramref name="deviceName"/> 查找，否则取第一个匹配类型的设备。
        /// </summary>
        public void Initialize(string? deviceName = null)
        {
            N36200? found = null;
            string? foundName = null;

            if (deviceName != null &&
                _deviceManager.DeviceMap.TryGetValue(deviceName, out var d) &&
                d is N36200 n)
            {
                found = n;
                foundName = deviceName;
            }
            else
            {
                foreach (var kv in _deviceManager.DeviceMap)
                {
                    if (kv.Value is N36200 n36)
                    {
                        found = n36;
                        foundName = kv.Key;
                        break;
                    }
                }
            }

            _device     = found;
            DeviceName  = foundName ?? "N36200 (未找到)";
            IsConnected = _device?.IsConnected ?? false;

            AppendLog(found != null
                ? $"已关联设备 [{DeviceName}]，连接状态：{(IsConnected ? "已连接" : "未连接")}"
                : "未在 DeviceManager 中找到 N36200 设备，请先初始化设备配置。");
        }

        public override void OnNavigatedTo(NavigationContext context)
        {
            var name = context.Parameters.GetValue<string?>("DeviceName");
            Initialize(name);
        }

        #endregion

        #region 辅助

        private CancellationToken Ct() => (_cts = new CancellationTokenSource(TimeSpan.FromSeconds(10))).Token;

        private async Task Exec(Func<Task> action)
        {
            if (_device == null)
            {
                AppendLog("错误：未关联到设备实例，请检查设备配置。");
                return;
            }
            if (IsBusy) return;
            IsBusy = true;
            try
            {
                await action();
                IsConnected = _device.IsConnected;
            }
            catch (OperationCanceledException)
            {
                AppendLog("命令超时或已取消。");
            }
            catch (Exception ex)
            {
                AppendLog($"错误：{ex.Message}");
            }
            finally
            {
                IsBusy = false;
            }
        }

        private void AppendLog(string message)
        {
            var line = $"[{DateTime.Now:HH:mm:ss}] {message}";
            ResponseLog = ResponseLog.Length > 4000
                ? line + "\n" + ResponseLog[..3000]
                : line + "\n" + ResponseLog;
        }

        #endregion

        public void Dispose()
        {
            _cts?.Cancel();
            _cts?.Dispose();
        }
    }
}
