using Logger;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Net.Http;
using System.Net.Sockets;
using System.Reflection;
using System.Runtime.Remoting.Contexts;
using System.Security.Cryptography;
using System.Security.Policy;
using System.Text;
using System.Threading.Tasks;
using WebApi.Helpers;
using WebApi.Models;

namespace WebApi.Tighten
{
    public class TightenServer
    {
        Dictionary<string,string> SendCode = new Dictionary<string,string>
        {
            { "connect", "0020 0001 0050 0001 0000" },  // 建立通讯
            { "heart", "00209999001000010000" },          // 心跳
            { "curve", "00200900000000000000" },          // 曲线
            { "result", "00200060001000010000" },          // 订阅结果
            { "tightenOk", "00200062001000000000" }          // 确认收到结果
        };
        public static event Action<string> ShowMsg; // 记录日志事件

        private bool _heartbeatRunning = false;

        public void InitTightenList()
        {
            RedTightenList();
            //Connect();
            StartHeartbeatLoop();
            StartReadData();
        }

        public void Connect()
        {
            try
            {
                foreach (KeyValuePair<string, TightenTool> kvp in Gl.TightenList)
                {
                    if (!kvp.Value.IsConnected)
                    {
                        kvp.Value.TcpClient.Connect(kvp.Value.IP, Convert.ToInt32(kvp.Value.Port));
                        if (kvp.Value.IsConnected)
                        {
                            string ErrMsg;
                            // 创建工具连接
                            if (!TightenHelpers.Send(kvp.Value.TcpClient, SendCode["connect"], out ErrMsg))
                            {
                                Log.Error(kvp.Value.IP + "：" +  ErrMsg);
                                return;
                            }
                            // 心跳
                            if (!TightenHelpers.Send(kvp.Value.TcpClient, SendCode["heart"], out ErrMsg))
                            {
                                Log.Error(kvp.Value.IP + "：" + ErrMsg);
                                return;
                            }
                            // 订阅结果
                            if (!TightenHelpers.Send(kvp.Value.TcpClient, SendCode["result"], out ErrMsg))
                            {
                                Log.Error(kvp.Value.IP + "：" + ErrMsg);
                                return;
                            }
                        }
                    }

                }
            }
            catch (Exception ex) {
                Log.FunError(ex, MethodBase.GetCurrentMethod().Name);
            }
        }

        private void RedTightenList()
        {
            SqlServer.ExecuteSql("SELECT * FROM PTCHV_基础表_拧紧枪", out DataTable dt, out string err);
            if (dt.Rows.Count > 0)
            {
                foreach (DataRow dr in dt.Rows) {
                    var tool = new TightenTool();
                    tool.OpName = dr["OpName"].ToString();
                    tool.Name = dr["Name"].ToString();
                    tool.IP = dr["IP"].ToString();
                    tool.Port = dr["Port"].ToString();
                    tool.TcpClient = new System.Net.Sockets.TcpClient();
                    Gl.TightenList.TryAdd(tool.IP, tool);
                }
            }
        }

        private bool SaveTightenData(string opName,string toolName,string max,string min,string OkValue,string value)
        {
            bool isOk = false;
            var param = new Dictionary<string, Object>{
                    { "工位号", opName },
                    { "拧紧枪名称", toolName },
                    { "上限值", max },
                    { "下限值", min },
                    { "标准值", OkValue },
                    { "值", value }
                };
            SqlServer.ExecuteProcedure("PTCHV_质量数据_增加", param, out DataTable dt, out string err);
            if (dt.Rows.Count > 0)
            {
                if(dt.Rows[0]["result"].ToString() == "1")
                {
                    isOk = true;
                }
            }
            return isOk;
        }

        // 开启心跳轮询 同时监听数据
        public void StartHeartbeatLoop()
        {
            foreach (var kvp in Gl.TightenList)
            {
                var tool = kvp.Value;
                Task.Run(async () =>
                {
                    while (true)
                    {
                        try
                        {
                            if (tool.TcpClient == null)
                                tool.TcpClient = new TcpClient();

                            if (!tool.IsConnected)
                            {
                                try
                                {
                                    tool.TcpClient.Close();
                                }
                                catch { }
                                tool.TcpClient = new TcpClient();
                                // 连接加超时
                                var connectTask = tool.TcpClient.ConnectAsync(tool.IP, Convert.ToInt32(tool.Port));
                                if (await Task.WhenAny(connectTask, Task.Delay(3000)) == connectTask)
                                {
                                    // 连接成功
                                    string errMsg;
                                    TightenHelpers.Send(tool.TcpClient, SendCode["connect"], out errMsg);
                                    TightenHelpers.Send(tool.TcpClient, SendCode["heart"], out errMsg);
                                    TightenHelpers.Send(tool.TcpClient, SendCode["result"], out errMsg);
                                    if(errMsg == "")
                                    {
                                        Log.Info($"拧紧枪【{tool.Name}】 连接成功！");
                                    }
                                }
                                else
                                {
                                    //Log.Error($"{tool.IP} 连接超时");
                                }
                            }
                            else
                            {
                                string errMsg;
                                TightenHelpers.Send(tool.TcpClient, SendCode["heart"], out errMsg);
                            }
                        }
                        catch (Exception ex)
                        {
                            Log.FunError(ex, "HeartbeatLoop");
                        }
                        await Task.Delay(10000);
                    }
                });
            }
        }

        public void StartReadData()
        {
            foreach (var kvp in Gl.TightenList)
            {
                Task.Run(async () =>
                {
                    while (true)
                    {
                        var tool = kvp.Value;
                        string ErrMsg = "";
                        try
                        {
                            var client = tool.TcpClient;
                            bool isConnected = false;
                            try
                            {
                                isConnected = client?.Client?.Connected ?? false;
                            }
                            catch (ObjectDisposedException)
                            {
                                isConnected = false;
                            }
                            catch (Exception ex)
                            {
                                Log.Error($"检查连接状态时发生意外错误 for {tool.IP}: {ex.Message}");
                                isConnected = false;
                            }

                            if (isConnected)
                            {
                                string command = "";
                                try
                                {
                                    if(client != null)
                                        command = TightenHelpers.Read(client, out ErrMsg);
                                    else
                                        continue;

                                    if(ErrMsg != "")
                                    {
                                        Log.Error("【ReadErr】"+kvp.Value.IP + "：" + ErrMsg);
                                    }

                                    if (command.Length == 232)
                                    {
                                        TightenHelpers.ParseTorqueData(command, out double min, out double max, out double target, out double actual);
                                        ShowMsg?.Invoke($"【{tool.OpName}{tool.Name} 拧紧数据】最小扭矩: {min}, 最大扭矩: {max}, 目标扭矩: {target}, 实际扭矩: {actual}");
                                        SaveTightenData(tool.OpName, tool.Name, max.ToString(), min.ToString(), target.ToString(), actual.ToString());
                                        await MqttServer.SendMqttMessageToOp(tool.OpName, "TightenOk", "1");
                                        // 发送确认前再次检查连接状态
                                        bool canSend = false;
                                        try
                                        {
                                            canSend = client?.Client?.Connected ?? false;
                                        } catch { /* ignore */ }

                                        if (canSend)
                                        {
                                            TightenHelpers.Send(client, SendCode["tightenOk"], out ErrMsg);
                                        }
                                    }
                                }
                                catch (Exception readSendEx) // 捕获读取或发送过程中的异常
                                {
                                    Log.Error($"读取或发送数据时出错 for {tool.IP}: {readSendEx.Message}");
                                    try { client?.Close(); } catch { }
                                    tool.TcpClient = null; // 标记以便下次循环重建
                                }
                            }
                        } catch (Exception outerEx) {
                            Log.FunError(outerEx, MethodBase.GetCurrentMethod().Name);
                        }
                        await Task.Delay(50);
                    }
                });
            }
        }
    }
}
