using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Net.Http;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using MesServerWork;
using System.Threading.Tasks;

namespace MesServerFunctions
{
    partial class FunctionMES
    {
        private readonly object _lockObject = new object();
        private volatile bool _isTestOk = false;
        private string _opName;
        private const int DEFAULT_TIMEOUT = 7000;    // 默认超时时间（毫秒）
        private const int MAX_RETRY_COUNT = 10;      // 最大重试次数
        private const int RESULT_LENGTH = 113;        // 预期结果长度

        /// <summary>
        /// 电阻测试
        /// </summary>
        private void ReqTestResistor(object e)
        {
            try
            {
                DeviceDriver_BasicData.CustomeEvetnArgs msgEvent = (DeviceDriver_BasicData.CustomeEvetnArgs)e;
                _opName = Convert.ToString(msgEvent.OpName);
                int tagValue = Convert.ToInt32(msgEvent.TagValue);

                if (tagValue == 1)
                {
                    TestResistor().GetAwaiter().GetResult();
                }
                else
                {
                    ResetPLCValues();
                }
            }
            catch (Exception err)
            {
                MyLog4Net.MyLogHelper.Error("电阻测试", $"测试过程发生错误: {err.Message}");
                ErrPLCValues();
            }
        }

        /// <summary>
        /// 执行电阻测试
        /// </summary>
        private async Task TestResistor()
        {
            TcpClient tcpClient = null;
            try
            {
                string IP = ConfigurationManager.AppSettings["ResistorDeviceIP_"+_opName];
                string Port = ConfigurationManager.AppSettings["ResistorDevicePort"];

                using (tcpClient = new TcpClient())
                {
                    var connectTask = tcpClient.ConnectAsync(IP, Convert.ToInt32(Port));
                    if (await Task.WhenAny(connectTask, Task.Delay(DEFAULT_TIMEOUT)) != connectTask)
                    {
                        throw new TimeoutException(_opName+"连接电阻仪超时");
                    }

                    if (tcpClient.Connected)
                    {
                        MyLog4Net.MyLogHelper.Info(_opName + "电阻测试", "电阻仪链接成功！");
                        await SendCommand(tcpClient, "01 09 64 00 05 00 00 00 00 00 73");

                        await Task.Delay(DEFAULT_TIMEOUT);

                        var readTask = Task.Run(() => Read(tcpClient));

                        int count = 0;
                        while (!_isTestOk && count < MAX_RETRY_COUNT)
                        {
                            await Task.Delay(1000);
                            await SendCommand(tcpClient, "03 01 04");
                            count++;
                        }

                        if (count >= MAX_RETRY_COUNT && !_isTestOk)
                        {
                            MyLog4Net.MyLogHelper.Error(_opName + "电阻测试", "测试超时，未收到有效结果");
                            ErrPLCValues();
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                MyLog4Net.MyLogHelper.Error(_opName + "电阻测试", $"测试过程发生错误: {ex.Message}");
                ErrPLCValues();
            }
            finally
            {
                if (tcpClient != null)
                {
                    tcpClient.Close();
                    MyLog4Net.MyLogHelper.Info(_opName + "电阻测试", "电阻仪链接关闭");
                }
            }
        }

        private void ResetPLCValues()
        {
            lock (_lockObject)
            {
                MIS_BASE.WritePLC(202, _opName, 0);
                MIS_BASE.WritePLC(203, _opName, 0);
                MIS_BASE.WritePLC(204, _opName, 0);
                MIS_BASE.WritePLC(34, _opName, false);
            }
        }

        private void ErrPLCValues()
        {
            lock (_lockObject)
            {
                MIS_BASE.WritePLC(202, _opName, 0);
                MIS_BASE.WritePLC(203, _opName, 0);
                MIS_BASE.WritePLC(204, _opName, 0);
                MIS_BASE.WritePLC(34, _opName, true);
            }
        }

        /// <summary>
        /// 发送命令到电阻仪
        /// </summary>
        private async Task SendCommand(TcpClient tcpClient, string command)
        {
            try
            {
                // 将空格分隔的HEX字符串转换为字节数组
                string[] hexValues = command.Split(' ');
                byte[] commandbyte = new byte[hexValues.Length];

                for (int i = 0; i < hexValues.Length; i++)
                {
                    commandbyte[i] = Convert.ToByte(hexValues[i], 16);
                }

                // 发送HEX格式的数据
                await tcpClient.Client.SendAsync(new ArraySegment<byte>(commandbyte), SocketFlags.None);

                // 记录发送的命令
                MyLog4Net.MyLogHelper.Info(_opName + "电阻测试Send", $"发送命令: {command}");
            }
            catch (Exception err)
            {
                MyLog4Net.MyLogHelper.Error(_opName + "电阻测试Send", $"发送命令失败: {err.Message}");
                throw;
            }
        }

        private void Read(TcpClient tcpClient)
        {
            try
            {
                while (!_isTestOk)
                {
                    if (tcpClient != null && tcpClient.Connected)
                    {
                        byte[] byteCommand = new byte[1024];
                        int icommand = tcpClient.Client.Receive(byteCommand);
                        string hexString = BitConverter.ToString(byteCommand, 0, icommand).Replace("-", " ");

                        if (hexString.Length == RESULT_LENGTH)
                        {
                            DataAnalysis(hexString);
                        }
                    }
                }
            }
            catch (Exception err)
            {
                MyLog4Net.MyLogHelper.Error(_opName + "电阻测试Read", err.Message);
            }
        }

        private void DataAnalysis(string hexString)
        {
            try
            {
                var byteArray = HexStringToByteArray(hexString.Replace(" ", ""));
                var start = 2;

                var 状态 = BitConverter.ToInt32(byteArray.Skip(start + 0).Take(4).ToArray(), 0);
                if (状态 != 2) return;
                var 电压V = BitConverter.ToDouble(byteArray.Skip(start + 4).Take(8).ToArray(), 0);
                var 电流A = BitConverter.ToDouble(byteArray.Skip(start + 12).Take(8).ToArray(), 0);
                var 电阻uΩ = BitConverter.ToDouble(byteArray.Skip(start + 20).Take(8).ToArray(), 0) * 1000000;
                var yyyy = BitConverter.ToUInt16(byteArray.Skip(start + 28).Take(2).ToArray(), 0);
                var MM = byteArray[start + 30];
                var dd = byteArray[start + 31];
                var HH = byteArray[start + 32];
                var mm = byteArray[start + 33];
                var ss = byteArray[start + 34];
                var datetime = $"{yyyy}-{MM}-{dd} {HH}:{mm}:{ss}";

                lock (_lockObject)
                {
                    MIS_BASE.WritePLC(202, _opName, 电压V);
                    MIS_BASE.WritePLC(203, _opName, 电流A);
                    MIS_BASE.WritePLC(204, _opName, 电阻uΩ);
                    MIS_BASE.WritePLC(34, _opName, true);
                    _isTestOk = true;
                }

                MyLog4Net.MyLogHelper.Info(_opName + "电阻测试", $"电阻结果写入完毕 【电压】{电压V}【电流】{电流A}【电阻】{电阻uΩ}");
            }
            catch (Exception ex)
            {
                MyLog4Net.MyLogHelper.Error(_opName + "电阻测试DataAnalysis", $"数据分析错误: {ex.Message}");
            }
        }

        public static byte[] HexStringToByteArray(string hex)
        {
            if (hex.Length % 2 != 0)
            {
                throw new ArgumentException("十六进制字符串长度必须是偶数");
            }

            byte[] bytes = new byte[hex.Length / 2];
            for (int i = 0; i < hex.Length; i += 2)
            {
                bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
            }
            return bytes;
        }
    }
}