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

namespace DeviceEditModule.ViewModels
{
    /// <summary>
    /// N69200 可编程直流电子负载控制面板 ViewModel。
    /// </summary>
    public class N69200ViewModel : NavigateViewModelBase, IDisposable
    {
        #region 私有字段

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

        #endregion

        #region 设备信息属性

        private string _deviceName = "N69200";
        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 DeviceWorkMode _selectedMode = DeviceWorkMode.CC;
        /// <summary>工作模式：CC / CV / CP / CR。</summary>
        public DeviceWorkMode SelectedMode
        {
            get => _selectedMode;
            set => SetProperty(ref _selectedMode, value);
        }

        private double _loadValue = 1.0;
        /// <summary>设定值（根据 SelectedMode 代表 A / V / W / Ω）。</summary>
        public double LoadValue
        {
            get => _loadValue;
            set => SetProperty(ref _loadValue, value);
        }

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

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

        private double _oppValue = 200.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 _currentMode = "—";
        /// <summary>当前负载模式（MODE? 查询结果）。</summary>
        public string CurrentMode
        {
            get => _currentMode;
            set => SetProperty(ref _currentMode, value);
        }

        private string _statusByte = "—";
        /// <summary>状态字节（*STB? 查询结果）。</summary>
        public string StatusByte
        {
            get => _statusByte;
            set => SetProperty(ref _statusByte, 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 InputOnCommand         { get; }
        public ICommand InputOffCommand        { get; }
        public ICommand SetModeCommand         { get; }
        public ICommand QueryModeCommand       { get; }
        public ICommand SetLoadValueCommand    { get; }
        public ICommand QueryAllMeasureCommand { get; }
        public ICommand QueryStatusCommand     { get; }
        public ICommand SetOvpCommand          { get; }
        public ICommand SetOcpCommand          { get; }
        public ICommand SetOppCommand          { get; }
        public ICommand ClearAlarmCommand      { get; }
   

        #endregion

        public N69200ViewModel(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("设备已重置"); }));
            InputOnCommand         = new DelegateCommand(async () => await Exec(async () => { await _device!.设置DC输入(true, Ct()); AppendLog("输入已开启"); }));
            InputOffCommand        = new DelegateCommand(async () => await Exec(async () => { await _device!.设置DC输入(false, Ct()); AppendLog("输入已关闭"); }));
            SetModeCommand         = new DelegateCommand(async () => await Exec(async () => { await _device!.设置负载模式(SelectedMode, Ct()); AppendLog($"模式已设为 {SelectedMode}"); }));
            QueryModeCommand       = new DelegateCommand(async () => await Exec(async () => { CurrentMode = await _device!.查询负载模式(Ct()); AppendLog($"当前模式: {CurrentMode}"); }));
            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"); }));
            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("保护告警已清除"); }));
  

            SetLoadValueCommand = new DelegateCommand(async () => await Exec(async () =>
            {
                switch (SelectedMode)
                {
                    case DeviceWorkMode.CC:
                        await _device!.设置恒电流CC(LoadValue, Ct());
                        AppendLog($"恒流 CC 已设为 {LoadValue} A");
                        break;
                    case DeviceWorkMode.CV:
                        await _device!.设置恒电压CV(LoadValue, Ct());
                        AppendLog($"恒压 CV 已设为 {LoadValue} V");
                        break;
                    case DeviceWorkMode.CP:
                        await _device!.设置恒功率CP(LoadValue, Ct());
                        AppendLog($"恒功率 CP 已设为 {LoadValue} W");
                        break;
                    case DeviceWorkMode.CR:
                        await _device!.设置恒电阻CR(LoadValue, Ct());
                        AppendLog($"恒电阻 CR 已设为 {LoadValue} Ω");
                        break;
                    default:
                        AppendLog($"模式 {SelectedMode} 不支持设置设定值");
                        break;
                }
            }));

            QueryStatusCommand = new DelegateCommand(async () => await Exec(async () =>
            {
                StatusByte = await _device!.读取状态字节(Ct());
                AppendLog($"状态字节: {StatusByte}");
            }));

            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

        public void Initialize(string? deviceName = null)
        {
            N69200? found = null;
            string? foundName = null;

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

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

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

        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();
        }
    }
}
