using Common.Attributes;
using DeviceCommand.Base;
using Model.Models;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Threading;
using System.Threading.Tasks;

namespace DeviceCommand.Devices
{
    [ACPCommand]
    public class IT6720 : Serial_Port // 直接继承您提供的 Serial_Port 基类
    {
        // 帧格式：同步头 AA + 地址 + 命令字 + 数据[4-25] + 校验和，共 26 字节
        private const byte FrameSyncByte = 0xAA;
        private const int FrameLength = 26;
        private readonly byte _deviceAddress; // 电源地址

        public IT6720(SerialPortConfig config, byte address = 0x00) : base(config)
        {
            _deviceAddress = address;
        }

        #region 核心协议封装（不变）

        /// <summary>
        /// 构建 26 字节的发送帧，并计算校验和
        /// </summary>
        private byte[] BuildFrame(byte command, byte[] dataBytes)
        {
            List<byte> frame = new List<byte> { FrameSyncByte, _deviceAddress, command };

            if (dataBytes != null && dataBytes.Length > 0)
            {
                frame.AddRange(dataBytes);
            }

            // 数据区必须占满 23 字节 (索引 3 到 24)
            while (frame.Count < 25)
            {
                frame.Add(0x00);
            }

            // 计算校验和：前 25 字节之和取低 8 位
            byte checkSum = 0;
            for (int i = 0; i < 25; i++)
            {
                checkSum += frame[i];
            }
            frame.Add(checkSum);

            return frame.ToArray();
        }

        /// <summary>
        /// 检查返回的 26 字节响应帧是否正确
        /// </summary>
        private bool ValidateResponseFrame(byte[] response)
        {
            if (response == null || response.Length != FrameLength) return false;
            if (response[0] != FrameSyncByte) return false;
            if (response[1] != _deviceAddress) return false;

            byte checkSum = 0;
            for (int i = 0; i < 25; i++)
            {
                checkSum += response[i];
            }
            return response[25] == checkSum;
        }

        /// <summary>
        /// 将实际电压/电流值转换成协议要求的整型 (乘以 1000 变成整形)
        /// </summary>
        private int ConvertToProtocolValue(double value)
        {
            return (int)Math.Round(value * 1000);
        }

        /// <summary>
        /// 将协议返回的 4 字节小端序转换为实际数值 (除以 1000.0)
        /// </summary>
        private double Convert4BytesToValue(byte b0, byte b1, byte b2, byte b3)
        {
            uint raw = (uint)(b0 | (b1 << 8) | (b2 << 16) | (b3 << 24));
            return raw / 1000.0;
        }

        /// <summary>
        /// 将协议返回的 2 字节小端序转换为实际数值 (除以 1000.0)
        /// </summary>
        private double Convert2BytesToValue(byte b0, byte b1)
        {
            ushort raw = (ushort)(b0 | (b1 << 8));
            return raw / 1000.0;
        }

        #endregion

        #region 1. 核心二进制收发方法（使用基类新方法）

        /// <summary>
        /// 发送命令帧并读取仪器返回的 26 字节数据帧
        /// </summary>
        private async Task<byte[]> SendAndReadFrameAsync(byte command, byte[] dataBytes, CancellationToken ct = default)
        {
            byte[] sendFrame = BuildFrame(command, dataBytes);

            // 使用基类提供的 WriteBytesAsync 发送二进制数据
            await WriteBytesAsync(sendFrame, ct).ConfigureAwait(false);

            // 使用基类提供的 ReadBytesAsync 读取定长 26 字节二进制数据
            // 注意：这里的 ReadTimeout 由基类统一控制
            return await ReadBytesAsync(FrameLength, ct).ConfigureAwait(false);
        }

        #endregion

        #region 2. 操作模式与输出控制

        /// <summary>
        /// 切换电源控制模式：PC 远程控制 / 面板控制
        /// </summary>
        public virtual async Task 切换远程控制模式(bool 远程控制 = true, CancellationToken ct = default)
        {
            byte[] data = new byte[] { (byte)(远程控制 ? 0x01 : 0x00) };
            byte[] response = await SendAndReadFrameAsync(0x20, data, ct);

            if (!ValidateResponseFrame(response))
                throw new Exception("IT6720 切换控制模式时通讯校验失败。");
        }

        public virtual async Task 切换本地控制模式(CancellationToken ct = default)
        {
            await 切换远程控制模式(false, ct);
        }

        /// <summary>
        /// 开启或关闭电源输出
        /// </summary>
        public virtual async Task 设置输出开关(bool 开启 = true, CancellationToken ct = default)
        {
            byte[] data = new byte[] { (byte)(开启 ? 0x01 : 0x00) };
            byte[] response = await SendAndReadFrameAsync(0x21, data, ct);

            if (!ValidateResponseFrame(response))
                throw new Exception("IT6720 设置输出时通讯校验失败。");
        }

        public virtual async Task<string> 查询输出开关状态(CancellationToken ct = default)
        {
            var (_, _, status) = await 查询实时测量值(ct);
            return (status & 0x01) != 0 ? "ON" : "OFF";
        }

        #endregion

        #region 3. 电压 / 电流设定

        /// <summary>
        /// 设置电源的电压上限
        /// </summary>
        public virtual async Task 设置电压上限(double 电压, CancellationToken ct = default)
        {
            int raw = ConvertToProtocolValue(电压);
            byte[] data = new byte[]
            {
                (byte)(raw & 0xFF), (byte)((raw >> 8) & 0xFF),
                (byte)((raw >> 16) & 0xFF), (byte)((raw >> 24) & 0xFF)
            };
            byte[] response = await SendAndReadFrameAsync(0x22, data, ct);
            if (!ValidateResponseFrame(response))
                throw new Exception("IT6720 设置电压上限时通讯校验失败。");
        }

        /// <summary>
        /// 设置电源的输出电压
        /// </summary>
        public virtual async Task 设置输出电压(double 电压, CancellationToken ct = default)
        {
            int raw = ConvertToProtocolValue(电压);
            byte[] data = new byte[]
            {
                (byte)(raw & 0xFF), (byte)((raw >> 8) & 0xFF),
                (byte)((raw >> 16) & 0xFF), (byte)((raw >> 24) & 0xFF)
            };
            byte[] response = await SendAndReadFrameAsync(0x23, data, ct);
            if (!ValidateResponseFrame(response))
                throw new Exception("IT6720 设置输出电压时通讯校验失败。");
        }

        /// <summary>
        /// 设置电源的输出电流限流值
        /// </summary>
        public virtual async Task 设置输出电流(double 电流, CancellationToken ct = default)
        {
            int raw = ConvertToProtocolValue(电流);
            byte[] data = new byte[]
            {
                (byte)(raw & 0xFF), (byte)((raw >> 8) & 0xFF)
            };
            byte[] response = await SendAndReadFrameAsync(0x24, data, ct);
            if (!ValidateResponseFrame(response))
                throw new Exception("IT6720 设置输出电流时通讯校验失败。");
        }

        #endregion

        #region 4. 读取实时数据与状态（对应 0x26H）

        /// <summary>
        /// 读取电源的实时电流、电压、设定值及电源状态
        /// 返回元组：实际电流(A), 实际电压(V), 状态字节(int)
        /// </summary>
        [Monitorable("IT6720 实时测量数据")]
        public virtual async Task<(double ActualCurrent, double ActualVoltage, int StatusByte)> 查询实时测量值(CancellationToken ct = default)
        {
            byte[] response = await SendAndReadFrameAsync(0x26, new byte[0], ct);

            if (!ValidateResponseFrame(response))
                throw new Exception("IT6720 读取数据时通讯校验失败。");

            double actualCurrent = Convert2BytesToValue(response[4], response[5]);
            double actualVoltage = Convert4BytesToValue(response[6], response[7], response[8], response[9]);
            int statusByte = response[10];

            return (actualCurrent, actualVoltage, statusByte);
        }

        [Monitorable("IT6720 实际电压")]
        public virtual async Task<string> 查询实际电压(CancellationToken ct = default)
        {
            var (_, voltage, _) = await 查询实时测量值(ct);
            return voltage.ToString("F2", CultureInfo.InvariantCulture);
        }

        [Monitorable("IT6720 实际电流")]
        public virtual async Task<string> 查询实际电流(CancellationToken ct = default)
        {
            var (current, _, _) = await 查询实时测量值(ct);
            return current.ToString("F3", CultureInfo.InvariantCulture);
        }

        /// <summary>
        /// 读取状态字，判断是否处于恒压 (CV) 模式或恒流 (CC) 模式
        /// 状态字节位详解：位 2,3 = 1(CV), 2(CC)
        /// </summary>
        public virtual async Task<string> 查询输出模式(CancellationToken ct = default)
        {
            var (_, _, status) = await 查询实时测量值(ct);
            int mode = (status >> 2) & 0x03;
            return mode switch
            {
                1 => "CV",
                2 => "CC",
                _ => "UNKNOWN"
            };
        }

        #endregion

        #region 5. 读取设备信息（命令字 31H）

        /// <summary>
        /// 读取电源的序列号、型号及软件版本
        /// </summary>
        public virtual async Task<string> 查询设备信息(CancellationToken ct = default)
        {
            byte[] response = await SendAndReadFrameAsync(0x31, new byte[0], ct);
            if (!ValidateResponseFrame(response)) return "Invalid Response";

            string model = System.Text.Encoding.ASCII.GetString(response, 4, 5).Trim('\0');
            string swVersion = $"{response[9]:X2}.{response[10]:X2}";
            string serialNum = System.Text.Encoding.ASCII.GetString(response, 11, 10).Trim('\0');

            return $"Model:{model}, SW:{swVersion}, SN:{serialNum}";
        }

        #endregion

        #region 6. 扩展系统命令（兼容接口）

        /// <summary>
        /// 基类自带的超时和清空缓冲区已经处理了大部分错误。
        /// 如需在面板显示具体错误，需通过状态位自行判断或查看面板 ERROR 灯。
        /// </summary>
        public virtual async Task<string> 查询错误信息(CancellationToken ct = default)
        {
            return "IT6720 无标准 SCPI 错误信息查询，请检查前面板 ERROR 指示灯。";
        }

        #endregion
    }
}